GroupJoin是LINQ用於實現兩個序列之間的查詢的操作符。它將兩個序列中的元素按照指定的鍵或多個鍵關聯起來,生成一個負責的結果序列。本文將從多個方面對GroupJoin進行詳細的闡述。
一、基礎概念
GroupJoin可以認為是Join和GroupBy的結合,將Join操作的結果根據指定的Key進行分組,生成一個鍵值對序列,其中鍵是指定的Key,值是Join操作生成的結果序列。下面是一個基本的GroupJoin語法:
var result = outerSequence.GroupJoin( innerSequence, outerKeySelector, innerKeySelector, (outerItem, innerItems) => new { outerItem, innerItems });
其中outerSequence和innerSequence是兩個待Join的序列,outerKeySelector和innerKeySelector是指定的鍵,用於將兩個序列中的元素進行關聯。Join操作生成的結果序列是一個匿名對象序列,每個匿名對象包含兩個屬性,outerItem和innerItems。outerItem表示外部序列中的每個元素,而innerItems是一個包含與outerItem關聯的內部序列元素的集合。可以使用LINQ中的Select方法從匿名對象序列中獲取需要的結果。
二、多條件選取
GroupJoin不僅可以使用單個鍵進行關聯,還可以使用多個鍵進行關聯。這種情況下,需要創建一個新的類型作為關鍵字。下面的示例中,將一個訂單列表和一個產品列表進行關聯,使用訂單的ProductID和Quantity作為關鍵字,查找購買每個產品的總數量:
class OrderProduct { public int ProductID { get; set; } public int Quantity { get; set; } } var result = orders.GroupJoin( products, order => new { order.ProductID, order.Quantity }, product => new { product.ID, Quantity = 1 }, (order, product) => new { ProductName = product.First().Name, TotalQuantity = order.Quantity * product.Count() });
其中,OrderProduct用於表示訂單中的每個產品,包含ProductID和Quantity屬性。GroupJoin使用了新創建的類型作為關鍵字,並通過Count方法獲取每個產品的總數量。
三、使用DefaultIfEmpty
如果主鍵不存在,GroupJoin默認會返回空集合。但是通過DefaultIfEmpty方法,可以指定一個默認值作為返回結果。下面的示例中,將沒有訂單的產品設置為0數量,並計算整個訂單的總價值:
var result = products.GroupJoin( orders, product => product.ID, order => order.ProductID, (product, orders) => new { Product = product, Orders = orders }) .SelectMany( x => x.Orders.DefaultIfEmpty(new Order { ProductID = x.Product.ID, Quantity = 0 }), (x, y) => new { ProductName = x.Product.Name, Price = x.Product.Price, Quantity = y.Quantity }) .GroupBy(x => x.ProductName) .Select(x => new { ProductName = x.Key, TotalValue = x.Sum(y => y.Price * y.Quantity) });
GroupJoin使用了產品的ID作為鍵,同時使用DefaultIfEmpty方法將沒有訂單的產品設置為0數量。在SelectMany方法中,使用GroupsJoin生成的結果和默認值生成一個新的匿名對象。最後通過GroupBy和Sum方法計算整個訂單的總價值。
四、使用into子句
GroupJoin + into語法可以讓查詢更加簡潔,同時避免重複執行一些查詢。下面的示例中,將訂單和產品關聯起來,並計算總價值和平均價值:
var result = orders.GroupJoin( products, order => order.ProductID, product => product.ID, (order, products) => new { Order = order, Products = products }) .GroupBy( x => x.Order.ID, y => y.Products, (k, g) => new { OrderID = k, TotalValue = g.Sum(x => x.Sum(y => y.Price * y.Quantity)), AverageValue = g.Average(x => x.Sum(y => y.Price * y.Quantity)) });
在第一個GroupJoin中生成包含訂單和產品信息的匿名對象,然後使用into將結果進行分組。在第二個GroupBy中,使用Sum和Average計算總價值和平均價值。
五、使用EqualityComparer
GroupJoin默認使用默認的相等比較器來比較鍵值相等性。但是,如果要使用自定義的相等比較器,可以通過重載方法來實現。下面的示例中,使用自定義的比較器,將部分訂單信息與產品信息進行關聯:
class OrderComparer : IEqualityComparer { public bool Equals(Order x, Order y) { return x != null && y != null && x.ProductID == y.ProductID && x.CustomerID == y.CustomerID; } public int GetHashCode(Order obj) { return obj.ProductID.GetHashCode() ^ obj.CustomerID.GetHashCode(); } } var result = orders.GroupJoin( products, order => order, product => new { ID = product.ID, Name = product.Name }, (order, products) => new { Order = order, Products = products }, new OrderComparer()) .SelectMany( x => x.Products.DefaultIfEmpty(), (x, y) => new { OrderID = x.Order.ID, ProductName = y?.Name ?? "No Product", TotalValue = x.Order.Quantity * y?.Price ?? 0 });
在GroupJoin方法中使用了一個自定義比較器來對訂單進行比較。比較器的Equals方法使用多個屬性比較訂單的相等性。在SelectMany方法中,使用GroupsJoin生成的結果和默認值生成一個新的匿名對象。
六、總結
通過本文的介紹,我們了解了GroupJoin操作符從基礎概念、多條件選取、使用DefaultIfEmpty、使用into子句、使用EqualityComparer等多個方面進行了詳細的闡述。在實際開發中,根據不同的需求,可以選用不同的GroupJoin語法來查詢所需數據,使得查詢結果更加準確、高效。
原創文章,作者:ZMZV,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/138649.html