2010-02-25 5 views
26

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

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

Теперь я мог бы написать один сохраненный proc («getUsersTeamsAndPermissions») или выполнить одну команду SQL «select * from Users», exec getTeams, выбрать * из «Разрешения».

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

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

+2

Если это ASP.Net, а сервер БД находится рядом с веб-сервером (или это только внутреннее приложение), то это, скорее всего, преждевременная оптимизация. – Earlz

+0

@Earlz, либо преждевременная оптимизация, либо исправление для какой-либо другой проблемы с дизайном. –

+6

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

ответ

8

Единственная команда из нескольких частей и сохраненные параметры процедуры, которые вы упоминаете, являются два варианта. Вы не можете делать их так, чтобы они «распараллеливались» на db. Однако оба этих варианта приводят к одному раунду , поэтому вы там хорошо. Невозможно отправить их более эффективно. В SQL Server 2005 и далее очень эффективная команда с несколькими параметрами.

Редактировать: добавлена ​​информация о том, почему вкратце один раз.

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

  • Я когда-то был ограничен жутким драйвером ODBC против мэйнфрейма, и на каждый вызов приходилось 1,2 секунды. Я серьезно. Были времена, когда я переполнял немного дополнительных в свои звонки. Не красиво.
  • Вы также можете оказаться в ситуации, когда вам нужно сконфигурировать ваши SQL-запросы где-то, и вы не можете просто сделать 3 вызова: это должно быть одно. Это не должно быть так, плохой дизайн, но это так. Вы делаете то, что должны делать!
  • Иногда, конечно, очень удобно инкапсулировать несколько шагов в хранимой процедуре. Обычно это не для сохранения поездок в оба конца, но для более сложных транзакций, получения идентификатора для новых записей, ограничения для разрешений, обеспечения инкапсуляции, бла-бла-бла. (But please don't start using stored procedures all the time.)
+0

Однократное путешествие в оба конца - это самое важное соображение. – tster

34

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

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

    } 
} 
+2

+1 для примера с хорошим кодом. Это то, о чем я говорил в вопросе с несколькими операторами sql в одной команде. – tster

+0

Спасибо за это, искали подходящий способ обработки соединений и команд :) – KristianB

0

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

как,

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

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

+0

, который сделал бы 4 круглых поездки;) – tster

+0

@tster, как это? – Earlz

2

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

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

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

+0

Я сделал это с головы. – tster

+0

+1 за то, что сказал мне не беспокоить. Поверьте мне, я буду делать много других вещей, прежде чем я начну это делать, так как веб-сервер и сервер баз данных довольно близки друг к другу. – tster

+0

Но я думаю, что MSTF должен реализовать какой-то объект (возможно, в объекте ObjectContext должно быть свойство IDisposable, которое при вводе будет выполнять все накопленные запросы за один раз, установив для каждого reslumenet строго типизированный. – Shimmy

0

Во-первых, 3 поездки в оба конца на самом деле не имеют большого значения. Если вы говорили о круглые поездки, то это было бы другим делом, но всего за 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 

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

1

I это this link может быть полезно.

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

+0

Пул соединений почти всегда гарантирует, что вы только откроете один физическое соединение, поэтому обычно вам не нужно беспокоиться о стоимости работы при открытии нескольких подключений. – Rory

Смежные вопросы