重用SqlConnection的最佳实践

时间:2014-12-29 15:57:11

标签: c# .net connection-pooling idisposable sqlconnection

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

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

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

5 个答案:

答案 0 :(得分:25)

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

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

缓存SqlConnection类的实例没有必要,也没有好的做法。

答案 1 :(得分:6)

MS SQL服务器管理其自己的连接池中的连接,并且它们实际上并未处理。但它们已关闭,因此您可以最小化网络流量并释放与服务器的可用连接。

另外你应该注意,如果你使用的是Linq-To-SQL,数据上下文在被处理之前不会释放连接,所以我建议你只使用已经运行的代码,不要试图自己优化它。

答案 2 :(得分:3)

正如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]);
                }
            }
        });

答案 3 :(得分:1)

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

答案 4 :(得分:-2)

是的,您可以创建全局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();