在ASP.NET中调用DB后,SQL的连接没有关闭

时间:2009-06-03 20:04:56

标签: asp.net sql-server-2005 sqlconnection

我有一个在ASP.NET中调用存储过程的通用方法:

public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
        {
            SqlDataReader iReader;
            SqlCommand sql = new SqlCommand();

            sql.CommandText = sprocName;
            sql.CommandType = CommandType.StoredProcedure;
            sql.Connection = ConnStr;
            if (SqlP != null)
            {
                foreach (SqlParameter p in SqlP)
                {
                    sql.Parameters.Add(p);
                }

            }
            sql.Connection.Open();
            iReader = sql.ExecuteReader(CommandBehavior.CloseConnection);
            sql.Dispose();

            return iReader;
        }

即使我正在调用CommandBehavior.CloseConnection,连接也没有关闭。我第一次请求页面时可以获得数据。在重新加载时,我收到以下错误:

  

连接未关闭。该   连接的当前状态是打开的。   描述:未处理的异常   在执行期间发生   当前的网络请求。请查看   堆栈跟踪以获取更多信息   错误及其来源   代码。

     

异常详细信息:   System.InvalidOperationException:The   连接没有关闭。该   连接的当前状态是打开的。

     

来源错误:

     

第35行:第36行:}行   37:sql.Connection.Open();   第38行:iReader =   sql.ExecuteReader(CommandBehavior.CloseConnection);   第39行:sql.Dispose();

最后如果我把sql.Connection.Close();在sql.Dispose()之前;我收到一个错误,iReader不可读,因为它已经关闭了。

显然我错误地关闭了我的连接,有人能指出我正确的方向吗?

4 个答案:

答案 0 :(得分:4)

返回DataReader时,底层连接必须保持打开状态。正确清理资源是消费者的责任。

public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
{
    SqlCommand sql = new SqlCommand();

    sql.CommandText = sprocName;
    sql.CommandType = CommandType.StoredProcedure;
    sql.Connection = ConnStr;
    if (SqlP != null)
    {
        foreach (SqlParameter p in SqlP)
        {
            sql.Parameters.Add(p);
        }

    }
    sql.Connection.Open();
    return sql.ExecuteReader(CommandBehavior.CloseConnection);          
}

public void ConsumingMethod()
{
    using(SqlDataReader reader = ExecuteStoredProc("MyProc", params))
    {
        while(reader.Read())
        {
            //work with your reader
        }
    }
}

答案 1 :(得分:1)

我建议使用“using”语句包装sql连接,这将解决大多数sql连接问题。

using (var conn = new SqlConnection("..."))
{
    conn.Open();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "...";
        using (var reader = cmd.ExecuteReader())
        {
            while (reader.Read())
            {
                // ...
            }
        }
    }

}

答案 2 :(得分:0)

想法是做一个Connection.Close();在完成SqlReader之后,基本上不是在SqlReader.Dispose()命令之前放置close()语句,而是应该将它放在下面。

答案 3 :(得分:0)

这是我处理IDataReader的首选方式。让调用者创建SqlConnection实例并传递给方法。

创建SqlConnection实例的成本很高。并且你最终会在不同情况下多次代码调用相同的ExecuteStoredProc方法。

因此,我通过添加SqlConnection实例作为参数的一部分来重构ExecuteStoredProc方法。

using (SqlConnection conn = new SqlConnection())
{
    conn.ConnectionString = // Connection String;
    conn.Open();

    using (IDataReader reader = foo.ExecuteStoredProc(conn, sprocName, SqlP))
    {
        // Process IDataReader
    }
}