我想知道以下代码模式:
static SqlConnection getcon()
{
SqlConnection con = new SqlConnection("data source=foobar..");
con.Open();
// is con Disposed automatically or will it leak and live
// forever when exception is thrown?
throw new Exception("exception");
return con;
}
static void Main(string[] args)
{
try
{
using (var scope = new TransactionScope())
using (var con = getcon())
using (var cmd = new SqlCommand("UPDATE SomeTable SET Column1 = 'test'", con))
{
cmd.ExecuteNonQuery();
scope.Complete();
}
}
catch
{
}
}
这是使用SqlConnection
(从getcon()
方法获取连接)的安全方式吗?当异常被抛出或永远存在时,它会在函数退出后被处理掉吗?
我想要这个GetCon()
方法的目的是缩短代码并将连接创建和打开包装在一行(using (var con = getcon())
..)
答案 0 :(得分:2)
你编写getcon方法的方式(我假设你专门测试了一些东西),con会在抛出异常时被释放。因为`return con;'在你抛出的异常之后,它将永远不会被返回到调用代码,并且一旦getcon退出就会被释放(超出范围)。
答案 1 :(得分:2)
is con Disposed automatically or will it leak and live orever when exception is thrown?
throw new Exception("exception");
return con;//your code
实际上return con;
行无法访问。换句话说,它永远不会在这里执行。你没有通过抛出con
来返回实际退出的Exception
方法。因此,您的连接将不会被清除here
。
当方法退出(异常)时,局部变量不在Scope
之内,并且您没有相同的托管引用,因此显然您的con
受Garbage Collection
的约束。< / p>
will it leak and live orever when exception is thrown?
答案是否定的,垃圾收集器将负责回收Connection
使用的内存,当Dispose(true)
通常从Finalizer
调用时,您的连接将被关闭。
修改强>
假设你的get con方法没有抛出任何异常并返回Connection
并且Exception
被抛出如下
using (var scope = new TransactionScope())
using (var con = getcon())
using (var cmd = new SqlCommand("UPDATE SomeTable SET Column1 = 'test'", con))
{
throw new Exception("Oops");//Throw excception somewhere here
cmd.ExecuteNonQuery();
scope.Complete();
}
自从您在con
语句中包装using
以来抛出异常时,上面的代码将保证清理。
希望这有帮助
答案 2 :(得分:1)
我认为jaadooviewer的答案是正确的,但似乎你可以通过在getcon方法中使用try / catch块完全避免这个问题。
try
{
SQLConnection con = new SQLConnection("...");
con.Open();
if (/*condition*/)
throw new Exception("Exception Condition Satisfied");
}
catch (Exception ex)
{
con.Dispose();
throw ex;
}
return con;