Как сделать несколько левых внешних объединений в запросе Linq? - PullRequest
0 голосов
/ 24 ноября 2010

Небольшой фон по запросу ниже. Ячейка имеет 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();

Этот запрос работает, но не эффективен. Он выполняет левое внешнее соединение в контейнере, но для каждой ячейки выполняет отдельный запрос для извлечения любых строк принтера, вместо того чтобы выполнять левое внешнее соединение в принтере.

Как я могу изменить это так, чтобы оно также выполняло левое внешнее соединение на столе принтера? Кстати, я хочу иерархический набор результатов. Таким образом, каждая ячейка должна иметь список контейнеров и список принтеров. Каждый из них, конечно, был бы пустым, если бы в ячейке не было ни одного.

Ответы [ 2 ]

3 голосов
/ 24 ноября 2010

Вот запрос для получения плоского результирующего набора с правильными левыми объединениями.

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 записей для какой-либо родительской записи, у вас было бы 1 миллион строк , каждая с копией родительской записи. В результате каждая дочерняя запись будет продублирована 10000 раз.

Всегда важно помнить, что с любым ORM он генерирует sql и возвращает плоские результирующие наборы, независимо от того, какой результат иерархической формы он в конечном итоге вам преподнесет.

1 голос
/ 24 ноября 2010

Обычно неправильно использовать join в 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")
            };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...