C# 在引发异常时处理SqlConnection
我想知道以下代码模式:C# 在引发异常时处理SqlConnection,c#,sqlconnection,C#,Sqlconnection,我想知道以下代码模式: 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 th
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()
方法的目的是缩短代码,并将连接的创建和打开包装在一行中(使用(var-con=GetCon())
)您编写GetCon方法的方式(我假设您是专门为了测试某个东西),一旦抛出异常,con就会被释放。自“return con;”起是在您抛出异常之后,它将永远不会返回到调用代码,并将在getcon退出时被释放(用于超出范围)。按照您编写getcon方法的方式(我假设您这样做是专门为了测试某些内容),一旦抛出异常,con就会被释放。自“return con;”起是在您抛出异常之后,它将永远不会返回到调用代码,并将在getcon退出时被释放(用于超出范围)。我认为Jaadoviewer的回答是正确的,但似乎您可以通过在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;
我认为Jaadoviewer的答案是正确的,但似乎可以通过在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;
实际返回con代码>行不可访问。换句话说,它永远不会在这里执行。您没有返回con
方法,而是通过抛出异常来实际退出。因此,您的连接将不会在此处清理
当方法退出时(异常情况下),局部变量超出了范围,并且您没有对该变量的托管引用,因此显然您的con
要进行垃圾收集
will it leak and live orever when exception is thrown?
答案是否定的,垃圾收集器将负责回收连接所使用的内存
,当Dispose(true)
通常从终结器
调用时,您的连接将关闭
编辑
假设您的get-con方法没有抛出任何异常,并返回一个连接
,而异常
被抛出,如下所示
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
包装到中
希望这有帮助
实际返回con代码>行不可访问。换句话说,它永远不会在这里执行。您没有返回con
方法,而是通过抛出异常来实际退出。因此,您的连接将不会在此处清理
当方法退出时(异常情况下),局部变量超出了范围,并且您没有对该变量的托管引用,因此显然您的con
要进行垃圾收集
will it leak and live orever when exception is thrown?
答案是否定的,垃圾收集器将负责回收连接所使用的内存
,当Dispose(true)
通常从终结器
调用时,您的连接将关闭
编辑
假设您的get-con方法没有抛出任何异常,并返回一个连接
,而异常
被抛出,如下所示
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”行中,而不是在花括号{}中,连接是否也会被处理掉呢?为了避免键入一行代码(conn.Open()
)而经历所有这些麻烦(可能会产生副作用和错误),这似乎是一种非常误导和过早的优化,不要这样做。这不值得。我已经编辑了你的标题。请看,“,其中的共识是“不,他们不应该”。好的!但是,即使异常发生在“using”行中,而不是在花括号{}中,连接是否也会被处理掉呢?为了避免键入一行代码(conn.Open()
)而经历所有这些麻烦(可能会产生副作用和错误),这似乎是一种非常误导和过早的优化,不要这样做。这里的主要问题是Using-block是否在getcon()
方法中扩展了它的触角not@Jaska-是的getcon()
是在using块内调用的,因此可以说它在块内。您可能希望将catch(Execption)
与throw结合使用代码>这样就不会丢失堆栈跟踪。(还有Dispose()
隐式调用Close()
用于SqlConnection
,因此您不需要在catch块中调用它)我不确定第一条注释是什么意思。感谢您对第二个问题的澄清。这里的主要问题是Using-block是否在getcon()
方法中扩展了它的触角not@Jaska-是的getcon()
是在using块内调用的,因此可以说它在块内。您可能希望将catch(Execption)
与throw结合使用代码>这样就不会丢失堆栈跟踪。(还有Dispose()
隐式调用Close()
用于SqlConnection
,因此您不需要在catch块中调用它)我不确定第一条注释是什么意思。谢谢你对第二条的澄清。