分组而不复制供应商行

Grouping without duplicating supplier row

使用 Linq-to-SQL 从 NorthWind 从 3 个表中获取数据时遇到问题:

  1. Suppliers
  2. Products
  3. Categories

我想获取 categoryId > 3 类别中所有产品的供应商。结果集每个供应商需要 1 行,然后是一些包含每个产品一行(包括类别信息)的子集。这个想法是这个结果集将从 ajax 调用中作为 json 值返回。

以下是我迄今为止最简单的版本:

from sups in Suppliers
join prods in Products on sups.SupplierID equals prods.SupplierID
join cats in Categories on prods.CategoryID equals cats.CategoryID
where ( cats.CategoryID > 3)

group sups by sups.SupplierID into g
select g

在 LinqPad 中,结果集似乎包含许多重复的供应商。 有什么想法吗?

已编辑: 感谢 Adduci 的回答,我得到了以下有效的 LINQ 语句:

from sups in Suppliers
join prods in Products on sups.SupplierID equals prods.SupplierID
join cats in Categories on prods.CategoryID equals cats.CategoryID
where cats.CategoryID > 3
group new { sups, prods, cats } by new { sups.SupplierID, sups.CompanyName } into g
select new 
{
  g.Key,
  ProductInfo = from x in g
                 select new
                 {
                    ProductProperty = x.prods.ProductName,
                    CategoryProperty = x.cats.CategoryName
                 }  
}

额外的 by new { sups.SupplierID, sups.CompanyName } 完成了包含供应商字段的结果集。不错!

连接表时经常出现这种情况。您通常可以使用 Distinct().

来解决这个问题

像这样:

(from sups in Suppliers
join prods in Products on sups.SupplierID equals prods.SupplierID
join cats in Categories on prods.CategoryID equals cats.CategoryID
where ( cats.CategoryID > 3)
group sups by sups.SupplierID into g
select g).Distinct()

第一步是使用匿名 class

将您的 3 个表分组在一起
group new { sups, prods, cats } 

而不是 select g 这是一个 (IGrouping<...>) 你应该像这样明确定义你想要的属性:

from sups in Suppliers
join prods in Products on sups.SupplierID equals prods.SupplierID
join cats in Categories on prods.CategoryID equals cats.CategoryID
where cats.CategoryID > 3
group new { sups, prods, cats } by sups.SupplierID into g
select new 
{
  Supplier = g.Key,
  ProductInfo = from x in g
                 select new
                 {
                    ProductProperty = x.prods.Prop1,
                    CategoryProperty = x.cats.Prop1
                 }  
}

这样您就可以防止从数据库返回未使用的信息