2009-09-04 80 views
3

这是一个简单的LINQ查询(基于NorthWind),它返回一个Customers列表。每个客户都包含订单列表。LINQ中的分层查询

from c in Customers 
join o in Orders on c.CustomerID equals o.CustomerID into CO 
select new {c, CO} 

这工作正常,生成的SQL也很好。现在我想更进一步。我希望每个Order对象都包含一个OrderDetails列表。我正在使用以下查询:

from c in Customers 
join od in (
    from o in Orders 
    join od in OrderDetails on o.OrderID equals od.OrderID into OD 
    select new { o.CustomerID, o, OD } 
) 
on c.CustomerID equals od.CustomerID into COD 
select new { c, COD } 

此查询工作但生成可怕的SQL。为每个客户发出单独的查询。当你看看我们的lambda代码:

Customers 
    .GroupJoin (
     Orders 
     .GroupJoin (
      OrderDetails, 
      o => o.OrderID, 
      od => od.OrderID, 
      (o, OD) => 
       new 
       { 
        CustomerID = o.CustomerID, 
        o = o, 
        OD = OD 
       } 
     ), 
     c => c.CustomerID, 
     od => od.CustomerID, 
     (c, COD) => 
     new 
     { 
      c = c, 
      COD = COD 
     } 
    ) 

嵌套的GroupJoins似乎是多个SQL状态的原因。但是,我尝试过各种组合,但没有成功。有任何想法吗?

编辑: 我可能一直不清楚我想达到的目标。我希望OrderDetail对象是Order对象的属性,它又是Customer对象的属性。我不希望Order & OrderDetail是Customer的属性。我正在尝试获取独特客户的名单。对于每个客户,我期望订单清单,并且对于每个订单,我需要一个OrderDetails清单。我希望层次结构比我的原始查询更深入一层。

回答

0

为什么不直接使用多个联接:

from c in Customers 
join o in Orders on c.CustomerID equals o.CustomerID 
join od in OrderDetails on o.OrderID equals od.OrderID 
select new {c, o, od} 
+0

虽然我不相信这个查询可以进行后处理,以得到他所需要的,原来的问题意味着他想要一个结果per'Customer',其中每个结果都包含一个'OrderDetails'列表。 – jeremyalan 2009-09-04 17:59:08

0

你可以尝试加入到服务器上的订单明细,然后在客户端上“重组”,让您充分分层数据结构:

var q = from c in Customers 
     join o in Orders on c.CustomerID equals o.CustomerID 
     join od in OrderDetails on o.OrderID equals od.OrderID into OD 
     select new { c, o, OD }; 

var res = from x in q.AsEnumerable() 
      group x by x.c.CustomerID into g 
      select new 
      { 
       Customer = g.First().c, 
       Orders = g.Select(y => new 
         { 
          Order = y.o, 
          OrderDetails = y.OD 
         }) 
      }; 
1

如果要强制单个查询,那么你可以对服务器端对客户端没有分组:

from a in (from c in Customers 
    join o in Orders on c.CustomerID equals o.CustomerID 
    join od in OrderDetails on o.OrderID equals od.OrderID 
    select new {c, o, od}).AsEnumerable() 
group a by a.c into g 
select new { Customer = g.Key, Orders = g.Select(o => o.o) , OrderDetails = g.Select(od => od.od)} 

生成的SQL是:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax], [t1].[OrderID], [t1].[CustomerID] AS [CustomerID2], [t1].[EmployeeID], [t1].[OrderDate], [t1].[RequiredDate], [t1].[ShippedDate], [t1].[ShipVia], [t1].[Freight], [t1].[ShipName], [t1].[ShipAddress], [t1].[ShipCity], [t1].[ShipRegion], [t1].[ShipPostalCode], [t1].[ShipCountry], [t2].[OrderID] AS [OrderID2], [t2].[ProductID], [t2].[UnitPrice], [t2].[Quantity], [t2].[Discount] 
FROM [Customers] AS [t0] 
INNER JOIN [Orders] AS [t1] ON [t0].[CustomerID] = [t1].[CustomerID] 
INNER JOIN [Order Details] AS [t2] ON [t1].[OrderID] = [t2].[OrderID] 

熊记住这是而不是快于多个查询,同时它增加了网络和服务器的负载。

我的建议是使用像查询以下内容:

DataLoadOptions opt = new DataLoadOptions(); 
opt.LoadWith<Orders>(o => o.OrderDetails); 
this.LoadOptions = opt; 

from c in Customers 
select new {c, Orders = c.Orders, OrderDetails = c.Orders.SelectMany(o=> o.OrderDetails)}