2013-04-18 2 views
0

У меня есть дизайн метод доступа выборки данных, ниже которого вызывает рекурсивно:Имеет ли несколько блоков запроса в одном соединении (SqlConnection)?

public static void DeleteRecord(SqlConnection connection, string childIds, string parentSheetname) 
{ 
    using (var adapter = new SqlDataAdapter("...", connection)) 
    { 
     //fill a datatable 
     string newIds = "..."; 
     string newParentName = "..."; 

     const string query = "DELETE FROM table " + 
          "WHERE ids in (@ids) AND parent = @parent"; 
     //Here's where recursion takes place 
     DeleteRecord(connection, newIds, newParentName); 

     using (var command = new SqlCommand(query, connection)) 
     { 
      var parameters = new[] { 
       new SqlParameter(...), new SqlParameter(...) 
      } 
      command.Parameters.AddRange(parameters); 
      command.ExecuteNonQuery(); 
     } 



} 

Мои вопросы:

  1. (Как хорошая практика) Можно ли передать соединение в виде параметр?

  2. Можно ли положить метод DeleteRecord на Task, поэтому каждый раз, когда я его вызываю, нет времени на выполнение команды для выполнения запроса. (конечно, есть где-то Task.WaitAll(tasks))

  3. В случае с номером 2, соединение будет блокировать несколько запросов, отправленных по серверу? Я столкнулся с тем, что SQLServer приостанавливает выполнение некоторых запросов, если он выполняет тяжелый запрос. (Пулы соединений включена по умолчанию, так что мне интересно, если это также случай, здесь по пункту 3)
+0

Вы должны использовать соединение по требованию - откройте его перед действием и освободите/закройте, когда это необходимо. Вы не должны держать соединение открытым, когда оно не используется. – MarcinJuraszek

+0

@MarcinJuraszek, что значит «когда он не используется»? В моем коде выше всегда используется объект 'connection'. Для каждого рекурсивного вызова потребуется 2 - 4 секунды. – Shermay

+0

Вам не следует пытаться использовать общий доступ к объектам подключения - в идеале, для каждого объекта команды необходимо создать новый объект подключения, открыть его, выполнить команду (и обработать любые результирующие наборы) и закрыть ее снова. За кулисами .NET сводит к минимуму количество * фактических * сетевых подключений (см. Пул соединений для получения дополнительной информации) –

ответ

1

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

Вы должны думать в наборах, а не о товарах. Передайте все элементы, которые нужно удалить сразу. См. Table-Valued Parameters для получения подробной информации о том, как достичь этого. Используйте один оператор DELETE, который объединяет весь набор параметров.

+0

Я буду перепроектировать его по методу 'think in sets' и использовать' where = 1' для создания динамических фильтров. Прежде чем вы ответите здесь, я подумал, буду ли я использовать ваш [ответ] (http://stackoverflow.com/questions/1544905/beginexecutenonquery-without-endexecutenonquery#1544978) при использовании 'command.BeginExecuteNonQuery() '. – Shermay

0

(Отвечая как ответ, как я не получаю добавить комментарий вариант) - @ MarcinJuraszek: +5 к нему. Размер пула по умолчанию равен 100 (макс.). Поэтому он будет приостанавливать последующие запросы больше, чем это. Чтобы преодолеть эту хорошую практику, нужно закрыть каждое открытое соединение, где это необходимо.

-когда он не используется? просто означает закрыть соединение в конце вашего кода. Неважно, сколько вашего кода требуется выполнить, он просто закроет соединение, когда достигнет указанного кода connection.close();

+0

Проходит «соединение», плохая идея? – Shermay

+0

Нет его ok.But не конкатенировать строки для создания команды SQL. Это дает вам широкое распространение для случайной или преднамеренной атаки SQL Injection, которая может уничтожить всю вашу базу данных. Вместо этого используйте параметризованные запросы. например SqlCommand cmd = new SqlCommand («Выберите uname, pswd из emp_details, где uname = (at) id и pswd = (at) password», conn); после этого оператора добавьте: cmd.Parameters.Add (новый SqlParameter ("(at) id", "id here")); cmd.Parameters.Добавить (новый SqlParameter («(at) password», «password here»)); –

+0

Вы видели это по моему вопросу? 'var parameters = new [] {SqlParameter (...), новый SqlParameter (...)}' – Shermay

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