以下查询的一些背景知识。 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应该有一个容器列表和一个打印机列表。如果没有单元格,那么每个都是空的。
答案 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")
};