lop*_*oni 5 c# linq linq-to-entities entity-framework
我正在开发一个应用程序,其中我有两个不同的实体,产品和ShoppingCarts.每种产品都是唯一的,并具有唯一的标识符.我想添加一个尚未出现在另一个购物车中但未出售给ShoppingCart的产品.
产品实体简化:
public class Products
{
public int Id { get; set; }
public string Name{ get; set; }
public bool Sold { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
购物车实体简化:
public class ShoppingCarts
{
public int Guid Guid { get; set; }
public int ProductId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
所以首先我检索所有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;
}
Run Code Online (Sandbox Code Playgroud)
出于某种原因,每隔一段时间,具有相同ProductId的2个实体将被添加到不同的购物车中.这使得该应用程序能够销售2个相同的产品.我最终通过在进行交易之前在应用程序中执行另一次检查来解决此问题.
我最近重新访问了代码并遇到了这些帖子 LINQ Query:确定一个列表中的对象是否存在于另一个列表中,基于 LINQ to Entity 键,加入NOT IN表
我的问题是,如果将我的查询更改为这样的内容将阻止双重添加.
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;
}
Run Code Online (Sandbox Code Playgroud)
如果有任何疑问,请告诉我,以便我能更好地解释这一点.
谢谢,
从原始查询中获取不同的记录可以获得所需的结果.注意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);
Run Code Online (Sandbox Code Playgroud)
您获得重复的原因是原始查询将为您提供产品表和购物车表之间匹配的列表.例如,如果你product1在cart1和cart2和product2中没有车,你会得到从加入下面的结果.
product1, cart1
product1, cart2
product2, null
Run Code Online (Sandbox Code Playgroud)
然后过滤掉空车
product1, cart1
product1, cart2
Run Code Online (Sandbox Code Playgroud)
然后,您只选择产品对象
product1
product1
Run Code Online (Sandbox Code Playgroud)
此时,您将留下重复的产品.我添加的不同功能将获取此列表并删除除一个重复条目之外的所有条目.离开你,
product1
Run Code Online (Sandbox Code Playgroud)
值得检查每个查询生成的sql,因为它们可能会有很大不同,即使它们产生类似的结果.我怀疑你的第一个查询将使用LEFT OUTER JOIN,而第二个查询将使用IN子句.我会使用LEFT OUTER JOIN,因为根据我的经验,IN子句相当慢,如果可能应该避免.显然你应该在自己的环境中测量它.
此外,您的第二个查询缺少where !p.Sold第一个查询.
| 归档时间: |
|
| 查看次数: |
10568 次 |
| 最近记录: |