簡體   English   中英

如何將 LINQ to SQL Distinct() 運算符應用於列表<T> ?

[英]How do I apply the LINQ to SQL Distinct() operator to a List<T>?

我的LINQ to SQL有一個嚴重的(讓我發瘋)問題。 我正在 Visual Studio 2010 中使用 c# 和 Razor 開發一個 ASP.NET MVC3 應用程序。

我有兩個數據庫表, ProductCategories

產品(Prod_Id[主鍵],其他屬性)

類別((Dept_Id,Prod_Id)[主鍵],其他屬性)

顯然,類別中的Prod_Id是外鍵。 這兩個類都使用實體框架 (EF) 進行映射。 為簡單起見,我沒有提及應用程序的上下文。

在類別中有多行包含Prod_Id 我想對類別中的所有Distinct Prod_Id進行投影。 我根據這個(非常簡單的)查詢在 SQL Server MGMT Studio 中使用普通 (T)SQL 做到了:

SELECT DISTINCT Prod_Id
FROM Categories

結果是正確的。 現在我需要在我的應用程序中進行這個查詢,所以我使用了:

var query = _StoreDB.Categories.Select(m => m.Prod_Id).Distinct();

我去檢查我的查詢結果使用:

query.Select(m => m.Prod_Id);

或者

foreach(var item in query)
{
  item.Prod_Id;
  //other instructions
}

它不起作用。 首先,當我嘗試編寫query.Select(m => m. or item.時的智能感知item.僅顯示有關方法的建議(例如 Equals 等...)而不是屬性。我認為可能有問題Intellisense(我猜你們中的大多數人很多次都希望 Intellisense 是錯誤的 :-D)但是當我啟動應用程序時,我在運行時收到一個錯誤。

在給出答案之前,請記住;

  1. 我檢查了很多論壇,我嘗試了普通的 LINQ to SQL(不使用 lambdas),但它不起作用。 它在 (T)SQL 中工作的事實意味着 LINQ to SQL 指令有問題(我的應用程序中的其他查詢工作正常)。

  2. 出於與應用程序相關的原因,我使用了List<T>變量而不是 _StoreDB.Categories,我認為這就是問題所在。 如果您能在不使用List<T>情況下為我提供解決方案,也將不勝感激。

這一行:

var query = _StoreDB.Categories.Select(m => m.Prod_Id).Distinct();

您的 LINQ 查詢很可能返回 IEnumerable... of ints (由Select(m => m.Prod_Id)判斷)。 您有整數列表,而不是實體對象列表。 嘗試打印它們,看看你得到了什么。

調用_StoreDB.Categories.Select(m => m.Prod_Id)意味着query包含Prod_Id值,而不是整個實體。 它大致相當於這個 SQL,它只選擇一列(而不是整行):

SELECT Prod_Id FROM Categories;

因此,當您使用foreach (var item in query)迭代query時, item的類型可能是int (或任何您的Prod_Id列),而不是您的實體。 這就是為什么 Intellisense 在您鍵入“ item. ”時不顯示您期望的實體屬性的原因。...

如果您希望Categories所有列都包含在query ,您甚至不需要使用.Select(m => m) 你可以這樣做:

var query = _StoreDB.Categories.Distinct();

請注意,如果您沒有明確地將IEqualityComparer<T>傳遞給Distinct() ,則將使用EqualityComparer<T>.Default (這可能會或可能不會按照您希望的方式運行,具體取決於T的類型,無論是或者它是否實現System.IEquatable<T>等)。

有關讓Distinct在與您類似的情況下工作的更多信息,請查看此問題此問題以及相關討論。

正如其他答案所解釋的那樣,OP 遇到的錯誤是因為他的代碼的結果是整數集合,而不是類別集合。

尚未回答的是他關於如何在連接中使用整數集合或其他內容以獲取一些有用數據的問題。 我將在這里嘗試這樣做。

現在,我不太確定為什么 OP 想要從類別中獲取 Prod_Id 的不同列表,而不僅僅是從項目中獲取 Prod_Id。 也許他想找出哪些產品與一個或多個類別相關,因此任何未分類的產品都會從結果中排除。 我將假設是這種情況,並且期望的結果是具有關聯類別的不同產品的集合。 我將首先回答有關如何處理 Prod_Ids 的問題,然后提供一些替代方案。

我們可以將問題中創建的 Prod_Ids 集合作為查詢:

var query = _StoreDB.Categories.Select(m => m.Prod_Id).Distinct();

然后我們將使用 join,像這樣:

var products = query.Join(_StoreDB.Products, id => id, p => p.Prod_Id,
               (id,p) => p);

這需要查詢,將它與 Products 表連接,指定要使用的鍵,最后說從每個匹配的集合中返回 Product 實體。 因為我們知道查詢中的 Prod_Ids 是唯一的(因為 Distinct()),而 Products 中的 Prod_Ids 是唯一的(根據定義,因為它是主鍵),所以我們知道結果將是唯一的,而不必調用 Distinct() .

現在,以上將獲得所需的結果,但這絕對不是最干凈或最簡單的方法。 如果 Category 實體定義了一個關系屬性,該屬性從 Products(可能稱為 Product)返回相關記錄,那么最簡單的方法來做我們正在嘗試做的事情如下:

var products = _StoreDB.Categories.Select(c => c.Product).Distinct();

這從每個類別中獲取產品並返回它們的不同集合。 如果 Category 實體沒有 Product 關系屬性,那么我們可以返回使用 Join 函數來獲取我們的產品。

var products = _StoreDB.Categories.Join(_StoreDB.Products, c => c.Prod_Id,
               p => p.Prod_Id, (c,p) => p).Distinct();

最后,如果我們不只是想要一個簡單的 Products 集合,那么還需要更多的東西,也許最簡單的事情就是在遍歷 Products 時處理它。 另一個示例是獲取每個產品所屬類別數的計數。 如果是這種情況,我會顛倒邏輯並從產品開始,如下所示:

var productsWithCount = _StoreDB.Products.Select(p => new { Product = p,
    NumberOfCategories = _StoreDB.Categories.Count(c => c.Prod_Id == p.Prod_Id)});

這將導致引用 Product 和與該 Product 相關的 NumberOfCategories 的匿名類型對象的集合。 如果我們仍然需要排除任何未分類的產品,我們可以在分號前附加.Where(r => r.NumberOfCategories > 0) 當然,如果 Product 實體是用相關類別的關系屬性定義的,則不需要它,因為您可以只使用任何 Product 並執行以下操作:

int NumberOfCategories = product.Categories.Count();

無論如何,對不起我漫無目的。 我希望這對遇到類似問題的任何其他人都有幫助。 ;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM