使用(var connection = new SqlConnection(“ConnectionString”))是否仍然关闭/处置错误连接?

时间:2011-09-26 08:12:49

标签: c# .net sql-server tsql sqlconnection

我有以下代码

try
{
    using (var connection = new SqlConnection(Utils.ConnectionString))
    {
        connection.Open();

        using (var cmd = new SqlCommand("StoredProcedure", connection))
        {                            
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            var sqlParam = new SqlParameter("id_document", idDocument);
            cmd.Parameters.Add(sqlParam);

            int result = cmd.ExecuteNonQuery();
            if (result != -1)
                return "something";

            //do something here

            return "something else";
        }
    }

    //do something
}
catch (SqlException ex)
{
    return "something AKA didn't work";
}

问题是:如果var connection括号(using)之间发生意外错误,{ }是否仍会关闭?

问题是我对存储过程的大多数调用是以这种方式进行的,最近我收到了这个错误:

  

System.InvalidOperationException:超时已过期。超时   从池中获取连接之前经过的时间段。这个   可能已经发生,因为所有汇集的连接都在使用中并且最大   达到了游泳池的大小。

我访问数据库的另一种方式是通过nHibernate。

5 个答案:

答案 0 :(得分:4)

using Statement (C# Reference)

  

using语句确保即使调用Dispose也会调用   在对象上调用方法时发生异常。您可以   通过将对象放在try块中来实现相同的结果   然后在finally块中调用Dispose;其实这是怎么回事   using语句由编译器翻译。代码示例   之前在编译时扩展为以下代码(请注意额外的   花括号来创建对象的有限范围):

答案 1 :(得分:3)

是的,如果它进入using语句的主体,它将被置于最后...是否正常到达块的末尾,通过返回语句退出,或者异常是抛出。基本上using语句相当于try / finally块。

这是的地方,您获得了连接吗?你的存储过程是否在某个地方陷入僵局,或许,就客户端代码而言,许多连接真正“忙”?

答案 2 :(得分:1)

就连接池用完可用连接而言,如果您处于分布式环境中并使用许多应用程序访问SQL Server但它们都使用相同的连接字符串,那么它们将全部使用相同的池服务器。要解决此问题,您可以通过将WorkstationID连接到Environment.MachineName来更改每个应用程序的连接字符串。这将使服务器将每个连接视为不同,并为每台计算机提供池而不是共享池。

在下面的示例中,我们甚至传入令牌以允许同一台计算机上的应用程序具有多个池。

示例:

    private string GetConnectionStringWithWorkStationId(string connectionString, string connectionPoolToken)
    {
        if (string.IsNullOrEmpty(machineName)) machineName = Environment.MachineName;

        SqlConnectionStringBuilder cnbdlr;
        try
        {
            cnbdlr = new SqlConnectionStringBuilder(connectionString);
        }
        catch
        {
            throw new ArgumentException("connection string was an invalid format");
        }

        cnbdlr.WorkstationID = machineName + connectionPoolToken;

        return cnbdlr.ConnectionString;
    }

答案 3 :(得分:0)

替换上面的代码......然后再次检查..

try
{
    using (var connection = new SqlConnection(Utils.ConnectionString))
    {
        connection.Open();
        using (var cmd = new SqlCommand("StoredProcedure", connection))
        {                            
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            var sqlParam = new SqlParameter("id_document", idDocument);
            cmd.Parameters.Add(sqlParam);

            int result = cmd.ExecuteNonQuery();
            if (result != -1)
                return "something";

            //do something here

            return "something else";

        }

        connection.Close();
        connection.Dispose();
    }

    //do something

}
catch (SqlException ex)
{
    return "something AKA didn't work";
}

答案 4 :(得分:0)

以下是参考资料:

http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

我所知道的是,如果你在using {}子句中使用一个对象,那么该对象继承了IDisposable接口(即SqlConnection继承了DbConnection,而DbConnection继承了IDisposable),这意味着如果你得到一个异常,任何对象都将是关闭并妥善处理。