抛出异常时处置SqlConnection

时间:2013-08-05 20:22:18

标签: 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 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()) ..)

3 个答案:

答案 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之内,并且您没有相同的托管引用,因此显然您的conGarbage 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;