我甚至不确定嵌套SqlConnections
是否可行,但我真的想远离它。我现在在我的代码中遇到了一个范围问题,我试图弄清楚如何绕过它。
所以直到最近我才有了一个全局SqlConnection
,它在应用程序启动时打开,在完成时关闭。我现在已经发现了.NET连接池的概念,所以我改变了我的代码,以便每个SqlCommand
(或其中一组)使用自己的,新创建和打开的, SqlConnection
,信任.NET来管理池和随之而来的开销。
我现在面临的问题是,我有几个代码块,看起来像这样:
using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString))
{
sqlConnection.Open();
using (SqlCommand sqlCommand1 = new SqlCommand("SQL code here", sqlConnection))
{
sqlCommand1.ExecuteNonQuery();
}
using (SqlCommand sqlCommand2 = new SqlCommand("SQL code here", sqlConnection))
{
sqlCommand2.ExecuteNonQuery();
}
.
.
.
ClassGlobal.WriteAction(action);
}
而ClassGlobal.WriteAction()函数看起来像这样:
public static void WriteAction(MyActionClass action)
{
using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString))
{
sqlConnection.Open();
using (SqlCommand sqlCommand = new SqlCommand("Write the action to the DB", sqlConnection))
{
sqlCommand.ExecuteNonQuery();
}
}
}
如您所见,在SqlConnection
内创建了一个新的WriteAction()
,它是从第一个SqlConnection
范围内调用的。不好!我试图避免这种情况。
在过去,由于没有这些using (SqlConnection)
块而且所有SqlCommands
都指向同一个(全局)SqlConnection
,所以不会出现问题。显然,我可以简单地将WriteAction()
的调用移到using (SqlCommand)
的结束大括号下方,但是:
action
实例经常在SqlConnection
的范围内进行实例化和填充,因此我必须进行更多更改(大量更改)以移动这些实例超出SqlConnection
范围。有很多它们会很多毛。WriteAction()
调用可以在SqlConnection
范围内,如上例所示,这样我就可以将所有内容都包含在TransactionScope
中到目前为止,这是不可能的,但肯定是个好主意。所以这就是我打算做的事情,但我想听听你们是否会认为这不是一个好的做法,或者你是否可以建议一个更好的方法。 (我最近发现我的全球SqlConnection
并不是一个很好的做法,而且它花了很多时间来修复它。我希望将来避免这样的发现。)
如何向WriteAction()
函数添加参数,使其如下所示:
public static void WriteAction(MyActionClass action, SqlConnection sqlConnection)
{
using (SqlCommand sqlCommand = new SqlCommand("Write the action to the DB", sqlConnection))
{
sqlCommand.ExecuteNonQuery();
}
}
这意味着,我可以简单地将WriteAction()
作为参数添加到函数的SqlConnection
,而不是将调用移到SqlConnection
范围之外的SQLCommand
。函数内部使用相同的连接,即使该连接已登记到TransactionScope
。
对于我从任何WriteAction()
范围之外调用SqlConnection
的少数实例,我可以编写一个如下所示的重载函数:
public static void WriteAction(MyActionClass action)
{
using (TransactionScope transactionScope = new TransactionScope())
{
using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString))
{
sqlConnection.Open();
WriteAction(action, sqlConnection);
}
transactionScope.Complete();
}
}
这看起来是个好主意还是我将在两年内再次做出这个决定?
答案 0 :(得分:2)
将SqlConnection
实例传递给方法绝对没问题。但是,我不确定你是否采用最后的方法,没有SqlConnection
的重载方法是个好主意。它隐藏了一个事实,你应该更好地使用另一个新的重载。它使代码编译阻止你修复现在应修复的代码。
请注意,using
块不是问题,而是打开的连接。只要您不打开连接,连接池就不需要打开物理连接。
因此,在致电WriteAction
之前关闭连接也是一个可行的选择:
using (SqlConnection sqlConnection = new SqlConnection(ClassGlobal.ConnectionString))
{
sqlConnection.Open();
using (SqlCommand sqlCommand1 = new SqlCommand("SQL code here", sqlConnection))
{
sqlCommand1.ExecuteNonQuery();
}
using (SqlCommand sqlCommand2 = new SqlCommand("SQL code here", sqlConnection))
{
sqlCommand2.ExecuteNonQuery();
}
// ...
sqlConnection.Close();
ClassGlobal.WriteAction(action);
// ... perhaps open it again here
}
来自MSDN:
每当用户在连接上调用
Open
时,pooler会查找 池中的可用连接。如果有可用的池连接, 它将它返回给调用者而不是打开新连接。什么时候 应用程序在连接上调用Close
,pooler返回它 汇集到一组活动连接而不是关闭它。一旦 连接返回到池中,可以重新使用它 下一次Open
来电。
因此,您可以看到using
中的嵌套WriteAction
不是问题,只要您不保持外部连接打开即可。不要将连接实例与物理连接混淆。