Выполните несколько команд SQL в одном распространении в прямом и обратном направлениях

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

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

Теперь я мог записать, что сингл сохранил proc ("getUsersTeamsAndPermissions"), или выполните единственный выбор "команды SQL * от Пользователей; должностное лицо getTeams; выберите * из Полномочий".

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

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

30
задан Patrick Karcher 25 February 2010 в 20:10
поделиться

5 ответов

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

Edit: добавление информации о том, зачем впихивать в один вызов.

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

  • Однажды я был ограничен убогим драйвером ODBC на мэйнфрейме, и каждый вызов занимал 1,2 секунды! Я серьезно. Были времена, когда я вставлял немного лишнего в свои вызовы db. Не очень красиво.
  • Вы также можете оказаться в ситуации, когда вам нужно где-то настроить sql-запросы, и вы не можете просто сделать 3 вызова: это должен быть один. Так не должно быть, плохой дизайн, но это так. Делайте то, что должны делать!
  • Иногда, конечно, может быть очень полезно заключить несколько шагов в хранимую процедуру. Обычно не для того, чтобы сэкономить на поездках туда и обратно, а для более жестких транзакций, получения ID для новых записей, ограничения прав доступа, обеспечения инкапсуляции, бла-бла-бла.
9
ответ дан 27 November 2019 в 23:59
поделиться

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

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());

    }
}
37
ответ дан 27 November 2019 в 23:59
поделиться

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

как в,

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

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

0
ответ дан 27 November 2019 в 23:59
поделиться

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

Тем не менее, я бы сделал это, вероятно, выполнив 3 сохраненных процесса с помощью 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

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

0
ответ дан 27 November 2019 в 23:59
поделиться

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

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

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

2
ответ дан 27 November 2019 в 23:59
поделиться