重用 SqlConnection 的最佳做法
本文关键字:最佳 SqlConnection 重用 | 更新日期: 2023-09-27 18:35:44
我来自Java经验,正在尝试从C#开始。我已经阅读了SqlConnection SqlCommand SqlDataReader IDisposable,我可以理解连接到数据库的最佳实践是将SqlConnection
,SqlCommand
和SqlDataReader
包装在他们自己的using
块中。
但是在Java中,我们用于将连接封装到工厂方法中,仅创建一次,并将其重用于所有查询,甚至是多线程查询。仅为每个查询创建语句和结果集并尽快关闭。
为每个查询创建一个新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();