2010-11-24 117 views
0

关于下面的查询的一点背景。细胞有1:M到容器和1:M与打印机。我想要一个查询,它将检索所有单元格和关联的容器(如果它们存在)以及关联的打印机(如果存在)。基本上我想在两个表上做一个左外连接。以下是我的查询:如何在Linq Query中执行多个左外连接?

var query = from cell in Cell 
    join container in Container.Where (row => row.SerialNumber == "1102141") on cell.CellID equals container.CellID 
    into containers 

    join printer in Printer.Where (row => row.Name == "PG10RelWarrPrt3") on cell.CellID equals printer.CellID 
    into printers 

    select new { Cell = cell, Containers = containers, Printers = printers }; 

query.Dump(); 

此查询有效,但效率不高。它在Container上执行左外连接,但对于每个单元,它执行单独的查询来检索任何Printer行,而不是在Printer上执行左外连接。

我该如何改变它,以便它还在打印机表上进行左外连接?顺便说一句,我想要一个分层结果集。 IOW,每个单元应该有一个容器列表和一个打印机列表。当然,如果没有单元格存在,每个元素都是空的。

+1

http://stackoverflow.com/questions/267488/linq-to-sql-multiple-left-outer-joins – diceguyd30 2010-11-24 13:23:21

+0

@ diceguyd30 - 我看到之前,我发布我的问题。这并不能解决我的问题。请注意,我声明我想要一个分层结果集,而不是一个平坦结果集。 DefaultIfEmpty()用于平坦的结果集。 – 2010-11-24 13:28:12

回答

2

下面是产生平坦的结果与正确的左联接设置查询。

var query = from cell in Cell 
    join container in Container.Where (row => row.SerialNumber == "1102141") on cell.CellID equals container.CellID 
    into containers 
    from container2 in containers.DefaultIfEmpty() 
    join printer in Printer.Where (row => row.Name == "PG10RelWarrPrt3") on cell.CellID equals printer.CellID 
    into printers 
    from printer2 in printers.DefaultIfEmpty() 
    select new { Cell = cell, Container = container2, Printer = printer2 }; 

您必须在本地后处理结果以获得所需的分层形状。

如果你编写这个后处理代码,你会明白为什么linq to sql不会为你处理多个兄弟集合。


为了使这更清晰,假设你有3件兄弟藏品。

如果对于某些父记录,所有三个兄弟集合都是空的,那么您将只有一条父母记录有一个空值。

如果所有三个兄弟集合都有一条父记录的100条记录,那么您将有百万行,每条记录都带有一条父记录的副本。每个儿童记录将在结果中重复10,000次。

要记住任何ORM总是很重要的,它会生成sql并获取平坦的结果集,而不管它最终呈现给您的是什么层次结构的结果。

1

It's usually wrong to use join in LINQ to SQL

尝试:

var query = from cell in Cell 
      select new 
      { 
       Cell = cell, 
       Containers = cell.Containers 
           .Where (row => row.SerialNumber == "1102141"), 
       Printers = cell.Printers 
           .Where (row => row.Name == "PG10RelWarrPrt3") 
      };