2010-12-14 6 views
82

У меня есть моя бизнес-логика, реализованная в простых статических классах со статическими методами. Каждый из этих методов открывает/закрывает соединение SQL при вызове:"открыть/закрыть" SqlConnection или оставить открытым?

public static void AddSomething(string something) 
{ 
    using (SqlConnection connection = new SqlConnection("...")) 
    { 
     connection.Open(); 

     // ... 

     connection.Close(); 
    } 
} 

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

//pass the connection object into the method 
public static void AddSomething(string something, SqlConnection connection) 
{ 
    bool openConn = (connection.State == ConnectionState.Open); 
    if (!openConn) 
    { 
     connection.Open(); 
    } 

    // .... 

    if (openConn) 
    { 
     connection.Close(); 
    } 
} 

Так что вопрос - я должен выбрать метод (а) или способ (б)? Я прочитал еще один вопрос о stackoverflow о том, что объединение пулов спасло производительность для меня, мне не нужно беспокоиться вообще ...

PS. Это приложение ASP.NET - соединения существуют только во время веб-запроса. Не win-приложение или услуга.

+1

Просто совет: используйте событие 'DbConnection.StateChange', чтобы отслеживать изменения состояния соединения (и может быть локально локально) вместо проверки свойства' DbConnection.State'. Это сэкономит вам стоимость исполнения. – decyclone

+1

Отсутствует одна деталь, так как этот метод является частью запроса страницы. Является ли это единственным методом, который называется или он является, как я предполагал в своем ответе, один из многих методов, который вызывается в вопросе страницы, он влияет на какой ответ прав;) –

+0

Дэвид - LOTS таких методов называются :) – Alex

ответ

59

Придерживайтесь опции a.

Пул соединений - ваш друг.

+23

ИМХО - он не должен даже закрывать. распоряжение сделает это. –

+2

@RoyiNamir Мне нравится вызов, чтобы закрыть соединение. Особенно для новичков и новичков в кодовой базе. Это более ясное и читаемое. – edhedges

+10

@edhedges Использование как «using», так и Close() в конечном итоге приведет к путанице для новичков. Они не собираются понимать цель использования «использования». Не используйте «Закрыть» вместо того, чтобы научить их цели «использования». Чтобы они научились лучше учиться и применять то, что они узнают, к другим частям кода. –

25

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

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

Однако вы делаете что-то вручную, поэтому вы можете изучить инструменты, которые управляют подключениями для вас, такие как DataSets, Linq to SQL, Entity Framework или NHibernate.

+0

Вы не должны нормально открывать и закрывать соединение в каждом вызове метода, только один раз для каждого запроса страницы. То, что я узнал, по крайней мере;) Время открытия и закрытия. –

+7

@David Martensson - соединения на самом деле не открываются и не закрываются при вызове SqlConnection.Open. ASP.NET перерабатывает активные соединения из пула, когда строка соединения соответствует ранее используемой строке подключения. Накладные расходы, связанные с этим, несущественны, и, кроме того, попытка «сделать это сама» означает, что вы должны принять все управленческие задачи, обеспечивающие, чтобы соединение по-прежнему активно для каждого последующего использования, что добавляет сложности и накладных расходов. При объединении пулов лучше всего открывать и закрывать его для каждого использования. –

+2

Со всем уважением, ответ «Всегда близкие связи» не очень подходит для вопроса ... Я их закрываю. Вопрос в том, когда. – Alex

66

Метод использования (a), каждый раз. Когда вы начнете масштабировать свое приложение, логика, связанная с состоянием, станет реальной болью, если вы этого не сделаете.

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

+3

Я бы поднял вас +50, если только мог :-) –

6

Существуют различия между физическими и логическими соединениями. DbConnection - это своего рода логическое соединение, и он использует базовое физическое соединение с Oracle. Закрытие/открытие DbConnection не влияет на вашу производительность, но делает ваш код чистым и стабильным - утечки соединения в этом случае невозможны.

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

Пул соединений освобождает вас от проверки состояния соединения - просто откройте, используйте и немедленно закройте их.

+0

Да, соединение не является соединением - т. Е. DbConnection не является физическим подключением. DbConnection - это класс .NET, который предоставляет методы и свойства для управления базовым физическим соединением. –

10

Отказ от ответственности: Я знаю, что это старый, но я нашел простой способ продемонстрировать этот факт, поэтому я вкладываю в свои два цента стоимости.

Если у вас возникли проблемы, полагая, что объединение действительно будет быстрее, а затем дать этому попытку:

Добавить следующее где:

using System.Diagnostics; 
public static class TestExtensions 
{ 
    public static void TimedOpen(this SqlConnection conn) 
    { 
     Stopwatch sw = Stopwatch.StartNew(); 
     conn.Open(); 
     Console.WriteLine(sw.Elapsed); 
    } 
} 

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

Для того, чтобы сделать это, вы можете добавить new StackTrace(true).GetFrame(1) +, чтобы позвонить в компанию WriteLine.

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