我来自Java经验,我试图从C#开始。我已阅读SqlConnection SqlCommand SqlDataReader IDisposable,我可以理解,连接到数据库的最佳做法是将SqlConnection
,SqlCommand
和SqlDataReader
包装在自己的using
块中
但在Java中,我们使用将连接封装到工厂方法中,只创建一次,并将其重用于所有查询,甚至是多线程查询。仅为每个查询创建语句和结果集,并尽快关闭。
是不是为每个查询创建一个新的SqlConnection
有点矫枉过正?不能重复使用吗?
答案 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();