我正在开发一个应用程序,其中有 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);
您得到重复项的原因是原始查询会为您提供产品表和购物车表之间的匹配项列表。例如,如果您在 cart1
和 cart2
中有 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/