在多线程服务器应用程序中访问SQL DB

时间:2010-02-20 08:47:12

标签: c# sql multithreading

在我的服务器应用程序中,我想使用DB(SQL Server),但我不确定最好的方法。有些客户端的请求来自线程池,因此它们的处理是异步的。每个请求通常都需要读取或写入DB,所以我在考虑静态方法,它将创建连接,执行查询并返回结果。我只担心打开和关闭连接是否太慢以及是否无法达到某些连接限制?这是好方法吗?

4 个答案:

答案 0 :(得分:1)

恕我直言,最好是依靠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实际上不会关闭它。它会将其返回到连接池,以便可以重复使用。

答案 1 :(得分:0)

我遇到了和你一样的问题。有一个巨大的应用程序,我开始制作多线程。受益于具有一个连接打开并正在重用的是,你可以问DB多次的数据作为新的连接要求(无需等待其他线程完成获取数据)产生了,并且例如,如果你松散连接到SQL(而当网络出现故障的第二个或两个),你将不得不经常检查连接是否反正提交查询之前打开它可能发生。

这是我在MS SQL中获取数据库行的代码,但其他内容应该以完全相同的方式完成。请记住,在sqlConnectOneTime(字符串varSqlConnectionDetails)有当没有连接,因此它需要一些修改为您的需求,或者如果SQL无法建立连接的查询将失败返回null的缺陷。你只需要在那里添加适当的代码处理:-)希望它对你有用: - )

    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;
    }

要点:

使用SQL Server的ConnectionDetails定义一个全局变量

建立连接的一种全局方法(你需要在那里处理null)

在完成读/写/更新方法时,使用using来处理连接,sql查询和所有内容。

答案 2 :(得分:0)

您没有告诉我们的一件事是,为您提供适合您的答案非常有用您期望服务器应用程序处于什么级别的负载

对于上述问题的几乎任何答案,答案是你不应该担心它。 ADO.net/Sql Server提供了连接池,它消除了从每个“var c = new SqlConnection(connectionString)”调用创建连接的一些开销。

答案 3 :(得分:0)

感到惊讶,没有人提到连接池。如果您认为您将有大量请求,为什么不设置一个池的最小池大小设置为25(此处为任意数字,不要拍摄),最大池大小设置为200。 这将减少连接尝试次数,并确保如果您没有泄漏连接句柄(您应该明确注意不要发生这种情况),您将始终有一个等待您的连接。 关于连接池的参考文章:http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx 另外注意,为什么需要在代码中有连接字符串?为了可维护性,将其设置在web.config或app.config中。我必须“修复”执行此类操作的代码,并且我总是对负责此类事情的程序员大肆宣誓。