Лучше всего передать открытый SqlConnection в качестве параметра или вызвать новый в каждом методе? - PullRequest
16 голосов
/ 21 марта 2012

Если методы / функции, которые я собираюсь вызвать, связаны с необходимостью открытого SqlConnection, я открою это в методе, который вызывает функцию. Например:

protected static void btnSubmit(){
   conn.Open();
   myMethod(someParam, conn);
   conn.Close();
}

protected static void myMethod(object someParam, SqlConnection conn){
   //Some SQL commands etc here..
}

Я делаю это так, чтобы я:

  • Только когда-либо открывайте и закрывайте 1 SqlConnection на процесс

Однако было бы лучше структурировать мой код следующим образом:

protected static void btnSubmit(){
   myMethod(someParam);
}

protected static void myMethod(object someParam){
   SqlConnection conn = New SqlConnection(".....");
   conn.Open();
   //Some SQL commands etc here..
   conn.Close();
}

Я вижу преимущество структурирования таким образом:

  • Мне не нужно передавать дополнительный параметр для каждого метода
  • Если позже в методе больше не будет команды SQL, не будет вызываться неиспользуемый параметр каждый раз

Недостаток, который я вижу в этом:

  • Если myMethod является рекурсивным методом, то когда он вызывает себя, он открывает еще один SqlConnection, и так далее, и так далее.
  • Если btnSubmit вызывает несколько методов, для которых требуется SqlConnection, каждый из них собирается открыть и закрыть новое соединение.

Каков наилучший способ сделать это, и какой наиболее часто практикуется?

Ответы [ 2 ]

17 голосов
/ 21 марта 2012

ADO.NET использует пул соединений, поэтому он автоматически использует уже открытое соединение, даже если вы думаете, что открываете новое соединение.Имея это в виду, на самом деле нет никакой причины передавать соединение через ваш код (как параметр).Это сделает ваш код намного чище с той же производительностью, что и при передаче соединения в качестве параметра.

Подробнее здесь

Также (и это действительно важно)Пожалуйста, используйте ключевое слово "using".Таким образом, вам не придется разбираться с закрытием соединения и очисткой, потому что ваш код в том виде, в котором он написан сейчас, не имеет отношения к закрытию соединений, поэтому в случае какого-то исключения вы можете столкнуться с достижением ограничения на числоваш сервер.Выполните что-то вроде этого:

using(var connection = new SqlConnection(<connection_string>))
{
  connection.Open();
  using(var command = connection.CreateCommand())
  {

  }
}

Как видите, нет необходимости вызывать connection.Close () или обрабатывать исключения и закрывать соединение в вашем блоке finally, потому что это"job" для блока "using".

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

12 голосов
/ 21 марта 2012

Лучшим шаблоном для использования является Репозиторий + UnitOfWork шаблонов.

Таким образом, создается и передается репозиторий UnitOfWork, который содержит соединение.После завершения работы UnitOfWork утилизируется.

// Pseudocode
using(UnitOfWork uow = new UnitOfWork())
{
   Repository.Init(uow);
   Repository.SaveInDb(stuff);
}

И Единица работы:

// PseudoCode
class UnitOfWork : IDisposable
{
   public UnitOfWork()
   {
      conn = new SqlConnection();
      conn.Open();
   }

   public void Dispose()
   {
       conn.Close();
   }

 ....

}

Это то, что я всегда использую.

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

...