Доступ к базе данных SQL в приложении многопоточного сервера - PullRequest
4 голосов
/ 20 февраля 2010

В моем серверном приложении я хочу использовать БД (SQL Server), но я совершенно не уверен в лучшем методе. Есть клиенты, чьи запросы поступают в пул потоков, поэтому их обработка выполняется асинхронно. Каждый запрос обычно требует чтения или записи в БД, поэтому я подумал о статическом методе, который бы создавал соединение, выполнял запрос и возвращал результат. Я только боюсь, что открытие и закрытие соединения не слишком медленное и не может ли быть достигнут некоторый лимит соединения? Это хороший подход?

Ответы [ 4 ]

1 голос
/ 20 февраля 2010

ИМХО, лучше всего полагаться на механизм пулов соединений ADO.NET и не пытаться обрабатывать соединения с базой данных вручную. Напишите ваши методы доступа к данным следующим образом:

public void SomeMethod()
{
    using (var connection = new SqlConnection(connectionString))
    using (var command = connection.CreateCommand())
    {
        connection.Open();
        command.CommandText = "SELECT Field1 FROM Table1";
        using (var reader = command.ExecuteReader())
        {
            while(reader.Read())
            {
                // do something with the results
            }
        }
    }
}

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

0 голосов
/ 20 февраля 2010

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

Для почти любого ответа на вышеупомянутый вопрос ответ будет таким: вам не стоит об этом беспокоиться. Сервер ADO.net/Sql обеспечивает пул соединений, который устраняет некоторые накладные расходы на создание соединений при каждом вызове «var c = new SqlConnection (connectionString)».

0 голосов
/ 20 февраля 2010

Удивлен, что никто не упомянул пул соединений. Если вы думаете, что у вас будет большое количество запросов, почему бы просто не настроить пул с минимальным размером пула, установленным в 25 (произвольное число здесь не снимать), а максимальный размер пула в 200. Это уменьшит количество попыток подключения и обеспечит, что если вы не пропускаете дескрипторы подключения (то, о чем вы должны позаботиться, чтобы не допустить), у вас всегда будет подключение, ожидающее вас. Справочная статья о пуле соединений: http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx Еще одно замечание: зачем нужна строка подключения в коде? Установите его в web.config или app.config для удобства обслуживания. Я должен был «исправить» код, который делал такие вещи, и я всегда обильно ругался на программиста, ответственного за такие вещи.

0 голосов
/ 20 февраля 2010

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

Это мой код для получения строк базы данных в MS SQL, но другие вещи должны выполняться точно так же. Имейте в виду, что sqlConnectOneTime (строка varSqlConnectionDetails) имеет недостаток возврата нуля, когда нет соединения, поэтому он нуждается в некоторых модификациях для ваших нужд, или запрос не будет выполнен, если sql не сможет установить соединение. Вам просто нужно добавить правильную обработку кода :-) Надеюсь, это будет полезно для вас: -)

    public const string sqlDataConnectionDetails = "Data Source=SQLSERVER\\SQLEXPRESS;Initial Cata....";

    public static string sqlGetDatabaseRows(string varDefinedConnection) {
        string varRows = "";
        const string preparedCommand = @"
                    SELECT SUM(row_count) AS 'Rows'
                    FROM sys.dm_db_partition_stats
                    WHERE index_id IN (0,1)
                    AND OBJECTPROPERTY([object_id], 'IsMsShipped') = 0;";
        using (var varConnection = Locale.sqlConnectOneTime(varDefinedConnection))
        using (var sqlQuery = new SqlCommand(preparedCommand, varConnection))
        using (var sqlQueryResult = sqlQuery.ExecuteReader())
            while (sqlQueryResult.Read()) {
                varRows = sqlQueryResult["Rows"].ToString();
            }
        return varRows;
    }


    public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails) {
        SqlConnection sqlConnection = new SqlConnection(varSqlConnectionDetails);
        try {
            sqlConnection.Open();
        } catch (Exception e) {
            MessageBox.Show("Błąd połączenia z serwerem SQL." + Environment.NewLine + Environment.NewLine + "Błąd: " + Environment.NewLine + e, "Błąd połączenia");
        }
        if (sqlConnection.State == ConnectionState.Open) {
            return sqlConnection;
        }
        return null;
    }

Описание:

Определена одна глобальная переменная с ConnectionDetails вашего SQL Server

Один глобальный метод для установления соединения (вам нужно обработать ноль там)

Использование using для удаления соединения, SQL-запроса и всего, когда метод чтения / записи / обновления выполнен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...