Я создаю приложение, и я хочу обработать несколько запросов в пакетном режиме в единственное распространение в прямом и обратном направлениях к базе данных. Например, позволяет, говорят, что единственная страница должна отобразить список пользователей, список групп и список полномочий.
Таким образом, я сохранил procs (или просто простые команды sql как "выбор * от Пользователей"), и я хочу выполнить трех из них. Однако для заполнения этой страницы я должен совершить 3 поездки в прямом и обратном направлениях.
Теперь я мог записать, что сингл сохранил proc ("getUsersTeamsAndPermissions"), или выполните единственный выбор "команды SQL * от Пользователей; должностное лицо getTeams; выберите * из Полномочий".
Но я задавался вопросом, был ли лучший способ определить, чтобы сделать 3 операции в единственном распространении в прямом и обратном направлениях. Преимущества включают быть легче в модульный тест и разрешение механизма базы данных параллелизировать запросы.
Я использую C# 3.5 и SQL Server 2008.
Однократная команда с несколькими частями и варианты хранимой процедуры, которые вы упомянули, - это два варианта. Вы не можете сделать их таким образом, чтобы они "распараллеливались" на БД. Однако оба этих варианта приводят к однократному обходу, так что вы в порядке. Нет способа отправить их более эффективно. В sql server 2005 и далее, многокомпонентная команда, которая полностью параметризована, очень эффективна.
Edit: добавление информации о том, зачем впихивать в один вызов.
Хотя вы не хотите слишком сильно заботиться о сокращении вызовов, могут быть законные причины для этого.
Что-то вроде этого . Пример, вероятно, не очень хорош, поскольку он не удаляет объекты должным образом, но вы понимаете. Вот очищенная версия:
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());
}
}
Создать временную таблицу? Вставьте все результаты в временную таблицу, а затем выберите * from @ temp-table
как в,
@temptable=....
select @temptable.field=mytable.field from mytable
select @temptable.field2=mytable2.field2 from mytable2
и т. Д. Только одно посещение базы данных, хотя я не уверен, что это на самом деле более эффективно .
Во-первых, три поездки туда и обратно не имеют большого значения. Если бы вы говорили о 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
Затем вы можете перебирать возвращенные наборы результатов, как если бы вы выполняли несколько наборов строк напрямую.
Сделать один цикл туда и обратно вместо трех будет действительно эффективнее. Вопрос в том, стоит ли это хлопот. Весь набор инструментов и фреймворк ADO.Net и C # 3.5 противостоит тому, что вы пытаетесь сделать. TableAdapters, Linq2SQL, EF, все они любят иметь дело с простой семантикой одного вызова == одного набора результатов. Таким образом, вы можете серьезно потерять продуктивность, пытаясь превзойти фреймворк на рассмотрение.
Я бы сказал, что воздержитесь, если у вас нет серьезных измерений, показывающих, что вам нужно уменьшить количество обходов. Если вы делаете , в конечном итоге требуя этого, то используйте хранимую процедуру, чтобы, по крайней мере, дать семантику API.
Но если ваш запрос действительно совпадает с тем, что вы опубликовали (например, выберите всех пользователей, все команды и все разрешения), то вы, очевидно, получите гораздо более крупную рыбу. для обжаривания, прежде чем сокращать круговые обходы ... сначала уменьшите наборы результатов.