Получение многомерного результата из хранимой процедуры с помощью LINQ to SQL - PullRequest
3 голосов
/ 09 июня 2009

Я использую LINQ to SQL для вызова хранимой процедуры с одиночным набором результатов (я нашел много информации об обработке нескольких наборов результатов, но это не то, что я делаю). На самом деле набор результатов - это все столбцы из 3 таблиц, соединенных вместе, и у меня есть сущности LINQ to SQL для этих 3 таблиц. Схема примерно такая:

  • Клиент 1
    • Заказ 1
      • Продукт 1
      • Продукт 2
      • Продукт 3
    • Заказ 2
      • Продукт 4
  • Клиент 2
    • Заказ 3
      • Продукт 5
    • Заказ 4
      • Продукт 6
      • Продукт 7

В основном, 1 клиент для многих заказов, 1 заказ для многих продуктов. Таким образом, результирующий набор хранимого процесса на самом деле представляет собой одну строку для каждого Продукта, но каждая строка включает все столбцы Заказ и Заказчик. В приведенном выше примере хранимый процесс будет возвращать 7 строк.

Таким образом, вопрос заключается в следующем: как я могу получить 2 объекта Customer из LINQ to SQL, каждый из которых заполнен своей коллекцией Orders, и каждый объект Order, имеющий свою коллекцию Products, заполнен всеми из результатов сохраненного процесса?

Я знаю, что если вы сделаете что-то вроде (dc - это LINQ to SQL DataContext) ...

var options = new DataLoadOptions();
options.LoadWith<Customer>(c => c.Orders);
dc.LoadOptions = options;

var customers = from c in dc.Customers select c;

... а затем просмотрите генерируемый SQL, он на самом деле запустит один оператор SQL, который соединит клиентов с заказами, выбрав все столбцы из обоих, а затем вернет вам отдельные объекты клиентов с заполненными коллекциями заказов. Мне нужен такой же перевод объектов, но по результатам моего сохраненного процесса.

Я попытался установить тип возврата моего сохраненного процесса для Customer, но в приведенном выше примере я получаю коллекцию из 7 объектов Customer (5 дубликатов), для которых не заполнена их коллекция Orders. Если после этого я переберу коллекцию Orders одного из объектов Customer, я увижу, что они лениво загружаются с другой передачей данных в базу данных. Затем я попытался установить тип возврата «Продукт», и я получаю 7 продуктов, но их свойство «Заказ» лениво загружается через другой круговой прием, если я пытаюсь получить к нему доступ.

Я также попытался обработать результат как IMultipleResults, вызвав GetResult () и GetResult () и GetResult () и вручную сложив их вместе. В этом случае, однако, только первый вызов GetResult <> () будет что-то возвращать (любой из трех типов сущностей будет работать, но только для первого вызова GetResult <> ()). Второй и третий вызовы GetResult <> () возвращают ноль.

Спасибо за любую помощь, которую может оказать любой. Я продолжаю думать, что либо упускаю что-то простое, либо LINQ to SQL не предлагает какого-либо общедоступного API для этого (даже несмотря на то, что он делает это самостоятельно в приведенном выше примере с LoadsWith).

1 Ответ

0 голосов
/ 26 ноября 2009

Лучшее решение, которое я мог придумать, это:

  1. Измените sproc для фактического возврата нескольких наборов результатов (Клиенты, Заказы и Продукты из приведенного выше примера)
  2. Используйте IMultipleResults как обычно (существует множество документов и примеров) на стороне LINQ to SQL, чтобы получить эти 3 отдельных IEnumerables
  3. Создание сгруппированных коллекций для каждого некорневого объекта, т. Е. var groupedOrders = allReturnedOrders.GroupBy(order => order.CustomerID) и var groupedProducts = allReturnedProducts.GroupBy(p => p.OrderID)
  4. Перебирайте неконечные объекты и используйте метод EntitySet.SetSource() для заполнения их коллекций связанных объектов, т.е. customer.Orders.SetSource(groupedOrders.Single(orderGroup => orderGroup.Key == customer.CustomerID)

Это получает ваши обычные объекты объектов из вашего DBML в памяти, и это не очень много кода (2-3 строки на уровень в иерархии, которую вы создаете). Это включает изменение sproc, но на самом деле это должно быть меньше передачи данных из вашей базы данных, поскольку вы не повторяете все данные более высокого уровня, как при объединении всех таблиц (повторение столбцов Customer и Order для каждого продукта в приведенном выше примере) .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...