同时调用多个 SQL Server 和同一连接

本文关键字:连接 Server 调用 SQL | 更新日期: 2023-09-27 18:35:36

我创建了全局静态类,它有一个SqlConnection,如下代码所示:

public class Globals
{
    public static SqlConnection SqlDbConn;
    public static OpenConnection(String ConnString)
    {
        SqlDbConn = new SqlConnection(ConnString);
        SqlDbConn.Open();              
    }
}

然后创建了Web服务,它具有多个功能。

我的问题是:如何在同一时间在所有功能中使用相同的连接(SqlDbConn)?也就是说,有多个用户同时调用这个Web服务,而Web服务中的每个函数使用相同的SqlDbConn,这是真的方式吗?如果不是为什么?

最后,在 Web 服务中,我使用此构造函数来初始化连接:

public class Service1 : System.Web.Services.WebService
{
    private static bool Initialized = false;
    static string ConnString= @"Data Source=192.168.1.1'SQLEXPRESS;UID=sa;PWD=0000;Initial Catalog=DBName; MultipleActiveResultSets=true";
    public Service1()
    {
        // This method called each function call
        if (!Initialized )
        {
            Globals.OpenConnection(ConnString);
            Initialized = true;
        }
    }
}

同时调用多个 SQL Server 和同一连接

您应该在每次调用数据库时创建一个新的 SqlConnection 实例,并在完成后Dispose它。SqlConnection 具有池化机制,可为您创建和重用连接。处理单个连接对象上的每个调用可能会在异步操作上引发会话繁忙异常

在"原始"ADO.NET 级别处理连接和命令的普遍接受的最佳实践是始终根据需要尽可能晚地创建这些对象,并尽快再次释放它们。 ADO.NET 已经内置了一个非常复杂的连接池机制 - 试图超越这种久经考验的机制是没有意义的。

为了确保正确处置对象,通常也可以将它们放入using(...) { ... }块中 - 如下所示:

// define query as a string
string query = "SELECT ..... FROM ... WHERE ......";
// create connection and command in "using" blocks
using (SqlConnection conn = new SqlConnection(-your-connection-string-here-))
using (SqlCommand cmd = new SqlCommand(conn, query))
{
    // set up e.g. parameters for your SqlCommand
    // open the connection, execute the query, close the connnection again
    conn.Open();
    // for a SELECT, use ExecuteReader and handle the reader (or use SqlDataAdapter to fill a DataTable)
    // for UPDATE, INSERT, DELETE just use a ExecuteNonQuery() to run the command
    using (SqlDataReader rdr = cmd.ExecuteReader())
    {
        while (rdr.Read())
        {
           // handle the data from the reader
        }
        // close reader
        rdr.Close();
    }
    conn.Close();
}

在存在线程的情况下,您的代码可能非常错误,并且在任何情况下,它都是连接池基础结构的糟糕副本,该基础结构已经以有效的方式重用物理连接。

但是,您不需要太多更改即可获得更好的方法

public class Globals
{
    // Keep global just the connection string 
    // (albeit you could simply pass it every time)
    public static string ConnString {get;set;};
    // Change the OpenConnection method to return the SqlConnection created 
    public static SqlConnection OpenConnection()
    {
        SqlConnection cnn = new SqlConnection(ConnString);
        cnn.Open();              
        return cnn;
    }
}
.....
public class Service1 : System.Web.Services.WebService
{
    private static bool Initialized = false;
    public Service1()
    {
        // This method called each function call
        if (!Initialized )
        {
            // Don't hard code the connectionstring details, read it from CONFIG
            // See ConfigurationManager class....
            string connectionString = ReadConnectionStringFromYourConfigFile()
            Globals.ConnString = connectionString;
            Initialized = true;
        }
    }
    // An usage example of your Globals
    public int GetDatabaseValue()
    {
         using(SqlConnection cn = Globals.OpenConnection())
         {
            .....
         } // Here the connection will be closed and disposed also in case of exceptions...
    }
}