如何在Linq查询中执行多个左外连接?

时间:2010-11-24 12:35:26

标签: linq linq-to-sql

以下查询的一些背景知识。 Cell的容量为1:M,打印机为1:M。我想要一个查询将检索所有单元格和相关容器(如果存在)和关联的打印机(如果存在)。基本上我想在两个表上做左外连接。这是我的查询:

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上执行左外连接,但是,对于每个Cell,它执行单独的查询以检索任何打印机行,而不是在打印机上执行左外连接。

如何更改此设置以便它还在Printer表上执行左外连接?顺便说一下,我想要一个分层结果集。 IOW,每个Cell应该有一个容器列表和一个打印机列表。如果没有单元格,那么每个都是空的。

2 个答案:

答案 0 :(得分:3)

这是一个生成具有正确左连接的平面结果集的查询。

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个兄弟收藏品。

如果所有三个兄弟集合对于某些父记录都是空的,那么你只有父记录1次带有一堆空值。

如果所有三个兄弟集合都有100条记录用于某些父记录,那么您将拥有 100万行,每行都有父记录的副本。每个子记录都会在结果中重复10,000次。

任何ORM都要记住它生成sql并获得平坦的结果集,无论它最终为您呈现的层次结构形式如何,这一点非常重要。

答案 1 :(得分: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")
            };