Выполнение нескольких команд SQL в одном цикле

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

поэтому я сохранил procs (или просто простые команды sql, такие как "выбрать * от пользователей"), и я хочу выполнить три из них. Однако, чтобы заполнить эту страницу, Я должен сделать 3 поездки туда и обратно.

теперь я мог бы написать один сохраненный proc ("getUsersTeamsAndPermissions") или выполните одну команду SQL"выберите * от пользователей;exec getTeams;выберите * от разрешений".

но мне было интересно, есть ли лучший способ указать, чтобы сделать 3 операции в одной поездке туда и обратно. Преимущества включают в себя упрощение модульного тестирования и возможность парраллелизации запросов компонентом database engine.

Я использую C# 3.5 и SQL Server 2008.

6 ответов


одна команда из нескольких частей и параметры хранимой процедуры, которые вы упомянули, являются двумя вариантами. Вы не можете сделать их таким образом, чтобы они были "распараллелены" на БД. Однако оба этих варианта приводят к одиночная поездка туда и обратно, Так что тут все хорошо. Нет способа отправить их более эффективно. В sql server 2005 и далее очень эффективна команда из нескольких частей, которая полностью параметризована.

редактировать: добавление информации на зачем втискиваться в один звонок.

хотя вы не хотите слишком заботиться о сокращении вызовов, там can быть законные основания для этого.

  • однажды я был ограничен вшивым драйвером ODBC против мейнфрейма, и на каждом вызове было 1,2 секунды накладных расходов! Я серьезно. Были времена, когда я немного зубрил extra в моей БД. Не очень.
  • вы также можете оказаться в ситуации, когда вам придется настройте свои SQL-запросы где-нибудь, и вы не можете просто сделать 3 вызова: это должен быть один. Это не должно быть так, плохой дизайн, но это. Делай, что должен!
  • иногда, конечно, может быть очень хорошо инкапсулировать несколько шагов в хранимой процедуре. Обычно не для сохранения поездок туда и обратно, но для более жестких транзакций, получения ID для новых записей, ограничения разрешений, обеспечения инкапсуляции, бла-бла-бла. (но, пожалуйста, не начинайте использовать сохраненные процедуры все время.)

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

using (var connection = new SqlConnection(ConnectionString))
using (var command = connection.CreateCommand())
{
    connection.Open();
    command.CommandText = "select id from test1; select id from test2";
    using (var reader = command.ExecuteReader())
    {
        do
        {
            while (reader.Read())
            {
                Console.WriteLine(reader.GetInt32(0));
            }
            Console.WriteLine("--next command--");
        } while (reader.NextResult());

    }
}

сделать один туда и обратно против трех будет более эффективным. Вопрос в том, стоит ли оно того. Весь ADO.Net и набор инструментов и фреймворк C# 3.5 противостоят тому, что вы пытаетесь сделать. TableAdapters, Linq2SQL, EF, все они любят иметь дело с простой семантикой one-call==one-resultset. Таким образом, вы можете потерять серьезную производительность, пытаясь победить фреймворк в подчинении.

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

но если ваш запрос действительно то, что вы выложили (т. е. выберите все пользователи все группы и все разрешения), то вы obviosuly есть гораздо больше рыбы, чтобы жарить, прежде чем уменьшить туда и обратно... сокращение первых результатах.


Я этой ссылка может быть полезной.

рассмотрите возможность использования по крайней мере того же соединения-открытия; согласно тому, что он говорит здесь, открытие соединения-это почти верхний лидер стоимости производительности в Entity-Framework.


во-первых, 3 туда и обратно не очень большое дело. Если бы вы говорили о 300 туда и обратно, тогда это было бы другое дело, но всего за 3 туда и обратно я бы кондерер это, чтобы определенно быть случаем преждевременной оптимизации.

тем не менее, я бы сделал это, вероятно, для выполнения 3 сохраненных procuedres с помощью SQL:

exec dbo.p_myproc_1 @param_1 = @in_param_1, @param_2 = @in_param_2
exec dbo.p_myproc_2
exec dbo.p_myproc_3

затем вы можете перебирать возвращенные наборы результатов, как если бы вы напрямую выполняется несколько наборов строк.


создать временную таблицу? Вставьте все результаты в таблицу temp, а затем select * from @temp-table

в,

@temptable=....
select @temptable.field=mytable.field from mytable
select @temptable.field2=mytable2.field2 from mytable2

etc... Только одна поездка в базу данных, хотя я не уверен, что она на самом деле более эффективна.