Как разрешить несколько запросов linq за одну операцию без использования базового запроса? - PullRequest
2 голосов
/ 06 мая 2009

У меня 14 запросов LINQ для разрешения одним способом. Ни у одного из них нет базового запроса, от которого я мог бы повесить их как подзапросы, а затем сохранить результаты как свойства экземпляра анонимного типа.

Вместо того, чтобы делать 14 отдельных вызовов в базу данных, как я могу гарантировать, что все они вызываются в одной и той же операции?

UPDATE

В итоге я использовал хитрый хак, который добился цели. Я знаю, что ВСЕГДА будет хотя бы один пользователь в пользовательской таблице, поэтому я использовал:

var data = (from tmp in DataContext.Users
            select new {
                Property1 = (from...),
                Property2 = (from...),
                PropertyN = (from...),
            }).First();

ОБНОВЛЕНИЕ 2

В одном из ответов подразумевалось, что это может привести к ошибкам MARS (множественный активный набор результатов). Что это за ошибки (я никогда их не видел), почему они происходят, и есть ли что-то неправильное во всей предпосылке этой линии вопросов? я ошибаюсь в своем утверждении, что запрос базы данных вернуть все за один раз будет быстрее / эффективнее, чем выполнение четырнадцати полностью отдельных запросов LINQ?

ОБНОВЛЕНИЕ 3

Я думаю, что мой подход избыточен и, с прагматической точки зрения, должен обрабатываться по-разному, либо с помощью хранимой процедуры, либо с помощью какого-либо подхода с задержкой / смешанным подходом.

Ответы [ 7 ]

3 голосов
/ 07 мая 2009

Вы по-прежнему делаете 14 отдельных обращений к базе данных через каждый из ваших подзапросов, вы просто делаете это в единственном экземпляре, когда вызывается ваш объект данных.

Edit:

Ошибка MARS возникает при наличии нескольких открытых считывателей данных для подключения. По умолчанию в SQl 2005 эта функция отключена. в вашем запросе, пока весь SQL передается за один раз, вы все еще возвращаете 14 читателей данных. Устройство чтения данных принимает это соединение исключительно, если только вы не указали этому соединению разрешение нескольких активных наборов результатов (MARS).

Чтобы решить эту проблему, вам нужно либо предварительно загрузить каждый из ваших подзапросов в список и запустить ваши подзапросы из этого списка, либо установить атрибут MutlipleActiveResultSet строки подключения = true.

<add name="Name" connectionString="Data Source=<server>;Initial Catalog=<database>;Integrated Security=True;MultipleActiveResultSets=true" providerName="System.Data.SqlClient"/>
0 голосов
/ 15 мая 2009

Не уверен, поможет ли это, но задаюсь вопросом, почему вы не используете ключевое слово let для улучшения запроса.

'let' позволяет запускать подзапросы и сохранять результаты во временной переменной, которую затем можно использовать в основном запросе

0 голосов
/ 14 мая 2009

Я не уверен, что выполнение запросов из таблицы Users действительно вам вообще помогает.

Прежде чем писать запросы LINQ, попробуйте подумать, как бы вы достигли своей цели с помощью базового SQL.

Я не уверен, что вы пытаетесь сделать именно потому, что вы не предоставили много кода, но, если бы вы делали это в хранимой процедуре, как бы это выглядело и что бы оно вернуло?

Я спрашиваю об этом, потому что, возможно, нужная вам структура данных просто не "вписывается" в один запрос.

Если это так, то вам просто нужно переосмыслить весь подход LINQ.

Может быть, вы могли бы предоставить больше информации о том, какие данные вы на самом деле пытаетесь получить и как?

ура

0 голосов
/ 13 мая 2009

Если вы переделываете свой «хитрый хак», он должен запускать запросы одновременно:

var data = from a in (from x in ... select x)
           from b in (from x in ... select y)
           from c in (from x in ... select z)
           select new { A = a, B = b, C = c };
var result = data.First();

Тем не менее, он выполнит полное объединение всех элементов, что, вероятно, не то, что вы хотели бы получить. Использование IQueryable.Concat может работать, если все запросы возвращают одинаковое количество столбцов:

var data = (from x in ... select new { Part = 1, Val = x })
    .AsQueryable() // may not be needed in your context
    .Concat(
        (from y in ... select new { Part = 2, Val = y })
            .AsQueryable()
            .Concat(
                (from z in ... select new { Part = 3, Val = z }).AsQueryable()
            )
    );
foreach (result in data)
{
    switch (result.Part)
    {
        // process each query's resultset
    }
}

Все еще хитрый (и не проверенный), но должен ударить по БД только один раз.

0 голосов
/ 13 мая 2009

Натан, вы говорите, что запросы не обязательно являются взаимозависимыми, но все они связаны. Нам нужно знать, являются ли они 14 различными наборами результатов или их можно объединить в один набор результатов. Если последнее, почему вы не можете создать представление или хранимую процедуру для этой цели? В некоторых ситуациях вам необходимо использовать суждение, чтобы определить, когда использовать другие маршруты для повышения производительности и выполнения работы. Смешивание подходов совсем не плохо.

Если вам нужно 14 различных наборов результатов, вы можете использовать несколько активных наборов результатов (MARS), включив его в строку подключения. Таким образом, они будут сделаны за один круг.

0 голосов
/ 13 мая 2009

Вы можете взять код SQL для каждого запроса, а затем отправить его в БД в виде одного пакета и, наконец, выполнить итерацию по 14 наборам результатов.

0 голосов
/ 06 мая 2009

Я не совсем уверен в ваших запросах, но вы можете инкапсулировать логику запроса в хранимой процедуре и перетащить ее с помощью конструктора контекста данных LINQ to SQL.

Если вам нужны результаты независимо и вы действительно не хотите получать информацию в оба конца на сервере базы данных, я думаю, вам следует вернуться к SqlDataReader и использовать NextResult, вызвав процедуру, которая извлекает все данные.

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