Join Operators
Cross Join
This sample shows how to perform a simple inner equijoin of two sequences to produce a flat result set that consists of each element in suppliers that has a matching element in customers.Code:
public void Linq102() { Listcustomers = GetCustomerList(); List suppliers = GetSupplierList(); var custSupJoin = suppliers.Join(customers, sup => sup.Country, cust => cust.Country, (sup, cust) => new { Country = sup.Country, SupplierName = sup.SupplierName, CustomerName = cust.CompanyName}); foreach (var item in custSupJoin) { Log.WriteLine("Country = {0}, Supplier = {1}, Customer = {2}", item.Country, item.SupplierName, item.CustomerName); } }
Result:
Group Join
A group join produces a hierarchical sequence. The following query is an inner join that produces a sequence of objects, each of which has a key and an inner sequence of all matching elements.Code:
public void Linq103() { Listcustomers = GetCustomerList(); List suppliers = GetSupplierList(); var custSupQuery = suppliers.GroupJoin(customers, sup => sup.Country, cust => cust.Country, (sup, cs) => new {Key = sup.Country, Items = cs}); foreach (var item in custSupQuery) { Log.WriteLine(item.Key + ":"); foreach (var element in item.Items) { Log.WriteLine(" " + element.CompanyName); } } }
Result:
Cross Join with Group Join
The group join operator is more general than join, as this slightly more verbose version of the cross join sample shows.Code:
public void Linq104() { string[] categories = new string[]{ "Beverages", "Condiments", "Vegetables", "Dairy Products", "Seafood" }; Listproducts = GetProductList(); var prodByCategory = categories.GroupJoin(products, cat => cat, prod => prod.Category, (cat, ps) => new {cat, ps}) .SelectMany(@t => @t.ps, (@t, p) => new {Category = @t.cat, p.ProductName}); foreach (var item in prodByCategory) { Log.WriteLine(item.ProductName + ": " + item.Category); } }
Result:
Left Outer Join
A left outer join produces a result set that includes all the left hand side elements at least once, even if they don't match any right hand side elements.Code:
public void Linq105() { Listcustomers = GetCustomerList(); List suppliers = GetSupplierList(); var supplierCusts = suppliers.GroupJoin(customers, sup => sup.Country, cust => cust.Country, (sup, cs) => new {sup, cs}) .SelectMany(@t => @t.cs.DefaultIfEmpty(),(@t, c) => new {@t, c}) .OrderBy(@t => @t.@t.sup.SupplierName) .Select(@t => new{ Country = @t.@t.sup.Country, CompanyName = @t.c == null? "(No customers)": @t.c.CompanyName, SupplierName = @t.@t.sup.SupplierName}); foreach (var item in supplierCusts) { Log.WriteLine("{0} ({1}): {2}", item.SupplierName, item.Country, item.CompanyName); } }
Result:
For each customer in the table of customers, this query returns all the suppliers from that same country, or else a string indicating that no suppliers from that country were found.
Code:
public void Linq106() { Listcustomers = GetCustomerList(); List suppliers = GetSupplierList(); var custSuppliers = customers.GroupJoin(suppliers, cust => cust.Country, sup => sup.Country, (cust, ss) => new {cust, ss}) .SelectMany(@t => @t.ss.DefaultIfEmpty(),(@t, s) => new {@t, s}) .OrderBy(@t => @t.@t.cust.CompanyName) .Select(@t => new{ Country =@t.@t.cust.Country, CompanyName = @t.@t.cust.CompanyName, SupplierName = @t.s == null? "(No suppliers)": @t.s.SupplierName}); foreach (var item in custSuppliers) { Log.WriteLine("{0} ({1}): {2}", item.CompanyName, item.Country, item.SupplierName); } }
Result:
For each supplier in the table of suppliers, this query returns all the customers from the same city and country, or else a string indicating that no customers from that city/country were found. Note the use of anonymous types to encapsulate the multiple key values.
Code:
public void Linq107() { Listcustomers = GetCustomerList(); List suppliers = GetSupplierList(); var supplierCusts = suppliers.GroupJoin(customers, sup => new {sup.City, sup.Country}, cust => new {cust.City, cust.Country}, (sup, cs) => new {sup, cs}) .SelectMany(@t => @t.cs.DefaultIfEmpty(), (@t, c) => new {@t, c}) .OrderBy (@t => @t.@t.sup.SupplierName) .Select(@t => new { Country = @t.@t.sup.Country, City = @t.@t.sup.City, SupplierName = @t.@t.sup.SupplierName, CompanyName = @t.c == null ? "(No customers)" : @t.c.CompanyName}); foreach (var item in supplierCusts) { Log.WriteLine("{0} ({1}, {2}): {3}", item.SupplierName, item.City, item.Country, item.CompanyName); } }