2

我有這樣的實體:EF查找實體不在列表中

產品

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; } 
} 

PriceListProduct

public class PriceListProduct 
{ 
    public int Id { get; set; } 
    public int PriceListId { get; set; } 
    public int ProductId { get; set; } 

    public virtual Product Product { get; set; } 
} 

的問題是,我怎麼能得到產品不在價目表中使用L INQ?

我的第一個想法是使用Contains,但產品列表可能大於100000,如果Contains被轉換爲WHERE NOT IN子句之類的查詢,那麼SQL的參數大約有2000個參數,所以除了性能外,我認爲這不是最好的方法。

還有別的辦法嗎?我應該使用原始查詢嗎?

更新#1

我想了解以下羣組加入回答@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 
+0

你是什麼意思「不在價目表」?即不在表格中,還是不在某個具體列表中? –

+0

不在表中。例如,如果有4種產品(P1,P2,P3,P4),並且我有一個包含P1和P3的價目表,我如何獲得產品P2和P4。 –

回答

0

查詢您是否嘗試過Join/GroupJoin? 我還沒有嘗試過對數據庫,看看生成的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); 

羣組加入將採取什麼在你的左表(db.Products),與什麼您的加盟右表(db.PriceListProducts.xxxxx)(參數1):左表中的每個產品將獲得右側匹配的列表,組合產品ID(參數2和3),輸出爲匿名類型(參數4)。將所有這些過濾到沒有產品價格的地方並選擇產品。這導致下面的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]) 
) 
+0

謝謝,我想我很接近,我正在使用GroupJoin,但結果並不是我期待的,請您檢查一下該帖子的更新嗎?我真的感謝你的幫助! –

2

所以你正在尋找Antijoin

手冊的做法可能是這樣的:

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; } 
} 

創建所有導航性能並讓EF爲您創建查詢

var query = db.Products.Where(p => !p.PriceLists.Any());