"открыть / закрыть" SqlConnection или оставить открытым? - PullRequest
102 голосов
/ 14 декабря 2010

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

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

        // ...

        connection.Close();
    }
}

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

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

    // ....

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

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

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

Ответы [ 6 ]

77 голосов
/ 14 декабря 2010

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

74 голосов
/ 14 декабря 2010

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

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

28 голосов
/ 14 декабря 2010

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

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

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

12 голосов
/ 05 апреля 2011

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

Если вам трудно поверить, что пул действительно будет быстрее, попробуйте:

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

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.

7 голосов
/ 14 декабря 2010

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

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

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

0 голосов
/ 25 июля 2018

Обычно вы должны поддерживать одно соединение для каждой транзакции (без параллельных вычислений)

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

Даже если ado.net имеет свой пул подключений, стоимость диспетчерских подключений очень низка, но повторное использование подключений - лучший выбор.

Почему бы не оставить в приложении только одно соединение

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

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

...