重用 SqlConnection 的最佳做法

本文关键字:最佳 SqlConnection 重用 | 更新日期: 2023-09-27 18:35:44

我来自Java经验,正在尝试从C#开始。我已经阅读了SqlConnection SqlCommand SqlDataReader IDisposable,我可以理解连接到数据库的最佳实践是将SqlConnectionSqlCommandSqlDataReader包装在他们自己的using块中。

但是在Java中,我们用于将连接封装到工厂方法中,仅创建一次,并将其重用于所有查询,甚至是多线程查询。仅为每个查询创建语句和结果集并尽快关闭。

为每个查询创建一个新SqlConnection是不是有点矫枉过正?不能重复使用吗?

重用 SqlConnection 的最佳做法

创建类的新实例 SqlConnection不会创建与 SQL Server 的新网络连接,而是租用现有连接(或创建新连接)。 .NET 会为您处理物理连接池。

完成连接(通过它可以发送多个查询)后,只需Close()Dispose()(或最好使用using{}块)。

没有必要,

也不是很好的做法,缓存SqlConnection类的实例。

正如VMAtm所说,.net会自行汇集连接,因此重新创建它们是完全可以的。 因此,我通常会为整个过程编写一个包装器,就像这样。

        public static void RunWithOpenSqlConnection(string connectionString, Action<SqlConnection> connectionCallBack)
    {
        SqlConnection conn = null;
        try
        {
            conn = new SqlConnection(connectionString);
            connectionCallBack(conn);
        }
        catch (Exception ex)
        {
            //Log Error Here
        }
        finally
        {
            if (conn != null)
                conn.Dispose(); //will close the connection
        }
    }
    public static void ExecuteSqlDataReader(string connectionString, string sqlCommand, Action<SqlDataReader> readerCallBack)
    {
        RunWithOpenSqlConnection(connectionString, delegate(SqlConnection conn)
        {
            SqlCommand cmd = null;
            SqlDataReader reader = null;
            try
            {
                cmd = new SqlCommand(sqlCommand, conn);
                reader = cmd.ExecuteReader();
                readerCallBack(reader);
            }
            catch (Exception ex)
            {
                //Log Error Here
            }
            finally
            {
                if (reader != null)
                    reader.Dispose();
                if (cmd != null)
                    cmd.Dispose();
            }
        });
    }
//Example calling these
            ExecuteSqlDataReader(ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString, "Select EmployeeID FROM Employees;", delegate(SqlDataReader reader)
        {
            List<string> employeeIds = new List<string>();
            if (reader.HasRows)
            {
                while(reader.Read())
                {
                    employeeIds.Add((string)reader[0]);
                }
            }
        });

MS SQL Server 管理其自己的连接池中的连接,并且它们实际上并未被释放。但是它们是关闭的,因此您可以最大限度地减少网络流量并释放与服务器的可用连接。

另外,您应该注意,如果您使用的是 Linq-To-SQL,则数据上下文在被释放之前不会释放连接,因此我建议您只使用已经工作的代码,不要尝试自己优化它。

要回答您的特定问题,您可以为每个查询重复使用一个SqlConnection。只需确保在运行另一个查询之前关闭当前查询(SqlDataReader等),即。将它们包裹在自己的using块中。

是的,您可以创建全局 SqlConnection 实例。就我而言,我使用 SqlConnection 作为我通过 Singleton 访问的 DataContext 的成员。

public class DatabaseDataContext : DataContext
{
    private static DatabaseDataContext instance;
    private SqlConnection sqlConnection;        
    private SqlTransaction sqlTransaction;
    //...
    public static DatabaseDataContext Instance
    {
        get
        {
            return instance ?? (instance = new DatabaseDataContext(connectionString));
        }
        set
        {
            instance = value;
        }
    }
}

您可以通过关闭和打开此连接来封装您的交易,即:

DatabaseDataContext.Instance.sqlConnection.Open();
// your transactions...
sqlConnection.Close();

或者,您可以保持连接处于打开状态,而是专门开始和结束事务:

DatabaseDataContext.Instance.sqlConnection.Open();
sqlTransaction = sqlConnection.BeginTransaction("Example Insert users");
try{
    // ...your first transaction
    sqlTransaction.Commit();
}
catch{sqlTransaction.Rollback();}
sqlTransaction = sqlConnection.BeginTransaction("Update baked breads");
try{
    // ...your second transaction
    sqlTransaction.Commit();
}
catch{sqlTransaction.Rollback();}
// Close the connection at some point
sqlConnection.Close();