我有一个在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不可读,因为它已经关闭了。
显然我错误地关闭了我的连接,有人能指出我正确的方向吗?
答案 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
}
}