Является ли использование единого для подключения хорошей идеей на веб-сайте ASP.NET

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

Я хочу знать, хорошая ли это идея, потому что сейчас у меня проблемы с этой ошибкой:

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

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

Вот код моего синглтона:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;

/// <summary>
/// This class take care of all the interaction with the database
/// </summary>
public class DatabaseFacade
{
    SqlConnection m_conn = null;

    string m_csLanguageColumn;

    //Variables that implement the Singleton pattern
    //Singleton pattern create only one instance of the class
    static DatabaseFacade instance = null;
    static readonly object padlock = new object();

    /// <summary>
    /// Private constructor. We must use Instance to use this class
    /// </summary>
    private DatabaseFacade()
    {
    }

    /// <summary>
    /// Static method to implement the Singleton
    /// </summary>
    public static DatabaseFacade Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new DatabaseFacade();
                }
                return instance;
            }
        }
    }

    /// <summary>
    /// Do the connection to the database
    /// </summary>
    public void InitConnection(int nLanguage)
    {
        m_conn = new SqlConnection(GetGoodConnectionString());

        try
        {
            //We check if the connection is not already open
            if (m_conn.State != ConnectionState.Open)
            {
                m_conn.Open();
            }

            m_csLanguageColumn = Tools.GetTranslationColumn(nLanguage);

        }
        catch (Exception err)
        {
            throw err;
        }
    }
}

Спасибо за вашу помощь!

13.10.2009 00:02:33
4 ОТВЕТА
РЕШЕНИЕ

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

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

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

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


Изменить: вы увидите упомянутую ошибку (время ожидания истекло до получения соединения из пула ), если вы не закрываете (или не удаляете) свои соединения. Убедитесь, что вы делаете это, как только вы закончите, используя каждое соединение.

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

23
23.05.2017 11:53:22
Хотя я согласен с тем, что синглтон - плохая идея для SqlConnection, я не вижу никаких признаков того, что он будет ограничен одним запросом. В коде нет блокировки, которая бы помешала нескольким пользователям объекта SqlConnection (что, во всяком случае, делает эту идею намного хуже из-за проблем с многопоточностью).
Mark Brackett 13.10.2009 00:21:32
@ Марк, дурак! Я написал это, не читая весь код, предполагая, что была блокировка, ограничивающая использование Соединения! Как вы заметили, это может вызвать совершенно другой класс проблем. Я обновил свой ответ, чтобы отразить это.
Jeff Sternal 13.10.2009 01:02:09
Спасибо, парни! Очень быстрый и понятный ответ. Это будет легко исправить! Еще раз большое спасибо!
Jean-François Côté 13.10.2009 10:34:08

Нет, это плохая идея. Вы используете пул соединений.

8
13.10.2009 00:03:50
Я не мог бы сказать это лучше. :-P
jrista 13.10.2009 00:12:14
Объяснение было бы хорошо.
Robert Harvey 13.10.2009 00:12:36
Ах даунвотерс, я люблю тебя. Никогда не сдавайся! @ Роберт: Я не объяснил дальше, так как есть лучшие ответы, за которые я проголосовал :)
Noon Silk 13.10.2009 02:52:23

Причина, по которой использование Соединения с базой данных в качестве одиночного является ужасной идеей, заключается в том, что каждое второе соединение + затем будет ДОЛЖНО ЖДАТЬ первого соединения, которое будет освобождено.

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

Это плохие новости.

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

Самая дорогая операция в объекте соединения с базой данных - это фактическое соединение . не творение.

4
13.10.2009 00:12:02