我正在开发一个应用程序,其中有2个不同的实体,Products和ShoppingCarts。每种产品都是唯一的,并具有唯一的标识符。我想添加一个尚未出现在另一个购物车中但未出售给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;
}
如果有任何疑问,请告诉我,以便我能更好地解释这一点。
谢谢,
答案 0 :(得分:5)
从原始查询中获取不同的记录可以获得所需的结果。注意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);
您获得重复的原因是原始查询将为您提供产品表和购物车表之间的匹配列表。例如,如果您在product1
cart1
cart2
和product2
以及product1, cart1
product1, cart2
product2, null
没有购物车,则会从加入中获得以下结果。
product1, cart1
product1, cart2
然后过滤掉空车
product1
product1
然后您只选择产品对象
product1
此时您将获得重复的产品。我添加的不同功能将获取此列表并删除除一个重复条目之外的所有条目。离开你,
where !p.Sold
值得检查每个查询生成的sql,因为它们可能会有很大不同,即使它们产生类似的结果。我怀疑你的第一个查询将使用LEFT OUTER JOIN,而第二个查询将使用IN子句。我会使用LEFT OUTER JOIN,因为根据我的经验,IN子句相当慢,如果可能应该避免。显然你应该在自己的环境中测量它。
此外,您的第二个查询缺少第一个查询中的{{1}}。
答案 1 :(得分:3)
我感觉你无意中咆哮了错误的树。
这是一个简单的场景:
基本上,您需要一个交易,关键部分,单身或类似设备,以确保只有一个人可以检查并将添加到购物车中单一操作 - 它必须成功或失败作为一个单一的工作单元。
答案 2 :(得分:1)
请查看此问题:LINQ to Entity, joining on NOT IN tables。比上述解决方案更清洁。
查看您的查询,没有任何内容可以防止重复记录显示。您需要使用此:How do I use Linq to obtain a unique list of properties from a list of objects?