c# - 哪个 LINQ 查询从 1 个表中选择不在另一个表中的行

标签 c# linq entity-framework linq-to-entities

我正在开发一个应用程序,其中有 2 个不同的实体:产品和购物车。每件产品都是独一无二的,并具有唯一的标识符。我想添加一个尚未在另一个购物车中且未出售给 ShoppingCart 的产品。

产品实体简化:

public class Products
{
    public int Id { get; set; }
    public string Name{ get; set; }
    public bool Sold { get; set; }
}

购物车实体简化:

public class ShoppingCarts
{
    public int Guid Guid { get; set; }
    public int ProductId { get; set; }
}

所以我首先检索所有 Product.Id,然后将它们添加到我的购物车。我的方法是这样的:

private IQueryable<Products> GetAvailableProductId(int quantity)
{
    var query = (from p in _context.Set<Products>()
                join sc in _context.Set<ShoppingCarts>() on p.Id equals sc.ProductId into subset
                from sc in subset.DefaultIfEmpty()
                where !p.Sold && sc == null
                select p).Take(quantity);
    return query;
}

出于某种原因,每隔一段时间,具有相同 ProductId 的 2 个实体被添加到不同的购物车。这使应用程序能够销售 2 种相同的产品。我最终通过在进行交易之前在应用程序中执行另一项检查来解决此问题。

我最近重新访问了代码并看到了这些帖子 LINQ Query: Determining if object in one list exists in another based on key LINQ to Entity, joining on NOT IN tables

我的问题是,将我的查询更改为这样的内容是否会阻止双重添加。

private IQueryable<Products> NewGetAvailableProductId(int quantity)
{
    var query = (from p in _context.Set<Products>()
                where !_context.Set<ShoppingCarts>().Any(x => x.ProductId == p.Id) &&  !p.Sold
                select p).Take(quantity);
    return query;
}

如有任何疑问,请告诉我,以便我更好地解释。

谢谢,

最佳答案

从您的原始查询中获取不同的记录应该会得到您想要的结果。注意 Take() 之前的 Distinct()。

var query = (from p in _context.Set<Products>()
                join sc in _context.Set<ShoppingCarts>() on p.Id equals sc.ProductId into subset
                from sc in subset.DefaultIfEmpty()
                where !p.Sold && sc == null
                select p).Distinct().Take(quantity);

您得到重复项的原因是原始查询会为您提供产品表和购物车表之间的匹配项列表。例如,如果您在 cart1cart2 中有 product1 并且没有购物车中有 product2 您将获得以下信息连接的结果。

product1, cart1
product1, cart2
product2, null

然后您过滤掉空购物车

product1, cart1
product1, cart2

然后您只选择产品对象

product1
product1

此时您只剩下重复的产品。然后,我添加的 distinct 函数将采用此列表并删除除一个重复条目之外的所有条目。留给你,

product1

值得检查每个查询生成的 sql,因为即使它们产生相似的结果,它们也可能完全不同。我怀疑您的第一个查询将使用 LEFT OUTER JOIN,而第二个查询将使用 IN 子句。我会使用 LEFT OUTER JOIN,因为根据我的经验,IN 子句相当慢,应尽可能避免使用。显然,您应该在自己的环境中对此进行测量。

此外,您的第二个查询缺少第一个查询中的 where !p.Sold

关于c# - 哪个 LINQ 查询从 1 个表中选择不在另一个表中的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11436242/

相关文章:

c# - 使用 Entity Framework 删除数据库

c# - 如何在 C#/XAML Windows 应用商店 (Metro UI) 应用程序中混合浅色和深色主题?

C# 指定的填充模式对此算法无效

c# - 在 linq 查询中获取计数

linq - 如何获取 linq groupby 中分组值的列表?

c# - 从 EF 4.0 ObjectContext 升级到 EF 6/6.1

c# - 在 C# 中的快捷方式后面复制文件

c# - Outlook 2010 VSTO 加载项 : UI freezes randomly,,同时将文件夹异步添加到 PST

c# - 从左连接中选择时出现 NullReferenceException

C# 如何通过向它添加属性来扩展存在于不同 dll 中的类?