Asp.net mvc EF查找不在列表中的实体
我有以下几点: 产品Asp.net mvc EF查找不在列表中的实体,asp.net-mvc,entity-framework,linq,ef-code-first,linq-to-entities,Asp.net Mvc,Entity Framework,Linq,Ef Code First,Linq To Entities,我有以下几点: 产品 public class Product { public int Id { get; set; } public string Name { get; set; } } 价目表 public class PriceList { public int Id { get; set; } public string Name { get;set; } } 价格表产品 public class PriceListProduct {
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
价目表
public class PriceList
{
public int Id { get; set; }
public string Name { get;set; }
}
价格表产品
public class PriceListProduct
{
public int Id { get; set; }
public int PriceListId { get; set; }
public int ProductId { get; set; }
public virtual Product Product { get; set; }
}
问题是,如何使用LINQ获得不在价目表中的产品
我的第一个想法是使用Contains,但是产品列表可能会超过100000个,如果Contains被转换为WHERE NOT IN子句这样的查询,SQL大约有2000个参数,所以除了性能之外,我认为这不是最好的方法
还有别的办法吗?我应该使用原始查询吗
更新1
我试图理解GroupJoin下面的@Indregaard答案。到目前为止,我有这个
var productsWithNoPrice = db.Product()
.GroupJoin(db.PriceListProduct().Where(plp => plp.PriceListId == 2)
.Select(plp => plp.Product),
p => p.Id,
plp => plp.Id,
(p, product) => new { p.Id, Product = product })
.Where(p => !p.Product.Any())
.Select(p => p.Product);
用过滤器
.Where(plp => plp.PriceListId == 2)
我正在从Id为2的价目表中筛选产品。我认为这很接近,但SQL生成的查询返回的行数与价目表中不存在但每一列都为空的产品数相对应
基本上我需要的是这样一个查询
select * from Product p
left join PriceListProduct plp on plp.ProductId = p.Id and plp.PriceListId = 2
where plp.Id is null
你试过了吗?
我还没有尝试过使用数据库来查看生成的sql是否有效/正常工作,但是使用常规对象时,类似这样的方法可以正常工作
var productsWithNoPrices = products.GroupJoin(productPriceList,
product => product.Id,
productprice => productprice.ProductId,
(product, productPrice) => new { Product = product, Prices = productPrice})
.Where(c=>!c.Prices.Any()).Select(c=>c.Product);
编辑:根据你更新的问题,我想你想要这样的东西:
var productsWithNoPrices = db.Products.GroupJoin(db.PriceListProducts.Where(c => c.PriceListId == 2),
product => product.Id,
productprice => productprice.ProductId,
(product, productPrice) => new { Product = product, Prices = productPrice }).Where(c=>!c.Prices.Any()).Select(c=>c.Product);
GroupJoin将获取左侧表db.Products中的内容,与右侧表db.PriceListProducts.xxxxx中的内容连接参数1:左侧表中的每个产品将从右侧获得匹配列表,并结合产品ID param 2和3,输出到匿名类型param 4。在没有productprice的地方过滤所有这些内容并选择产品。这将导致以下SQL,它似乎给出了所需的结果
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[Products] AS [Extent1]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[PriceListProducts] AS [Extent2]
WHERE (2 = [Extent2].[PriceListId]) AND ([Extent1].[Id] = [Extent2].[ProductId])
)
所以你在找
手动方法可以是这样的:
var query =
from p in db.Products
join plp in db.PriceListProducts
on p.Id equals plp.ProductId into priceLists
where !priceLists.Any()
select p;
另一种方式:
var query = db.Products
.Where(p => !db.PriceListProducts.Any(plp => p.Id == plp.ProductId));
但最好的方法是在模型中创建所有导航属性
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<PriceListProduct> PriceLists { get; set; }
}
你说不在价目表上是什么意思?i、 e.不在表中,或不在某些具体清单中?不在表中。例如,如果有4种产品P1、P2、P3、P4,并且我有一个包含P1和P3的价目表,我如何才能获得产品P2和P4。谢谢,我想我很接近了,我正在使用GroupJoin,但结果不是我所期望的,你能检查一下帖子的更新吗?我真的很感谢你的帮助!!
var query = db.Products.Where(p => !p.PriceLists.Any());