开发者

How to do multiple left outer joins in a Linq Query?

开发者 https://www.devze.com 2023-01-27 06:08 出处:网络
A little background on the query below. Cell has a 1:M to Container and a 1:M with Printer. I want a query that will retrieve all Cells and associated containers, if they exist, and associated printer

A little background on the query below. Cell has a 1:M to Container and a 1:M with Printer. I want a query that will retrieve all Cells and associated containers, if they exist, and associated printers, if they exist. Essentially I want to do a left outer join on both tables. Here is the query I have:

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 => ro开发者_JAVA百科w.Name == "PG10RelWarrPrt3") on cell.CellID equals printer.CellID
    into printers

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

query.Dump();

This query works, but is not efficient. It does a left outer join on Container, but, for each Cell, it performs a separate query to retrieve any Printer rows, instead of also doing a left outer join on Printer.

How can I change this so that it also does a left outer join on the Printer table? BTW, I want a hierarchical result set. IOW, each Cell should have a list of containers and a list of printers. Each would be empty of course, if none existed for the cell.


Here's a query to produce a flat result set with correct left joins.

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 }; 

You'll have to post-process the results locally to get the hierarchical shape desired.

If you write this post-processing code, you'll understand why linq to sql doesn't process multiple sibling collections for you.


To make this clearer, suppose you had 3 sibling collections.

If all three sibling collections were empty for some parent record, you'd have just the parent record 1 time with a bunch of nulls.

If all three sibling collections had 100 records for some parent record, you'd have 1 million rows, each with a copy of the parent record. Every child record would be duplicated 10,000 times in the result.

It's always important to keep in mind with any ORM that it generates sql and gets back flat result sets, no matter what hierarchically shaped result it eventually present you with.


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

Try:

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")
            };
0

精彩评论

暂无评论...
验证码 换一张
取 消