关闭SQLDataReader - 如何判断它们是否已关闭?

时间:2012-05-08 21:38:45

标签: c# database-connection connection-pooling sqldatareader

我发现我遇到了一些网站连接池问题,而我正在跟踪它们。我知道有一件事要确保任何SQLDataReaders都关闭,我已经走了,并确保它们是。我脑海中浮现的一个问题是关于返回SQLDataReaders的方法以及它们如何关闭(或不关闭)。

所以这里有我设置的东西和一些示例方法:

public static SqlDataReader ExecuteReader(SqlCommand cmd)
{
    SqlConnection c = new SqlConnection(Properties.Settings.Default.DatabaseConn);
    cmd.Connection = c;
    c.Open();
    return cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
}

然后我有一个使用'ExecuteReader()'

的方法
public static SqlDataReader GetData()
{
  SqlCommand Query = new SqlCommand("select * from SomeTable");
  return ExecuteReader(Query);
}

现在说我有另一个调用'GetData'的方法。我显然简化了事情。

public static SqlDataReader GetMoreData()
{
  return GetData;
}

所以我的问题是,当我像这样调用'GetMoreData'时

SqlDataReader dr = GetMoreData();
//do some stuff with 'dr'
dr.close();

所有我的SqlDataReaders和连接是否正确关闭?

谢谢!

4 个答案:

答案 0 :(得分:4)

描述

SqlDataReader实现了IDisposable接口。 在每个实现IDisposable的课程中,您应致电Dispose或使用using 为了释放资源,在这种情况下关闭阅读器和底层连接。

  

IDisposable接口定义释放已分配资源的方法。

示例

using(SqlDataReader dr = GetMoreData()) 
{
    try
    {   
       // do your stuff
    }
    catch(Exception ex)
    {
       // handle the exception
    }
} // the reader will get closed here

SqlDataReader dr;
try
{   
    dr = GetMoreData();
    // do your stuff
}
catch(Exception ex)
{
   // handle the exception
}
finally
{
   // close the reader
   dr.Dispose();
}

修改

JotaBe

的好评
  

但是如果他实现了一个返回DataReader的方法,则应该在方法的调用者中使用using。因此,无法保证DataReader已关闭。

我不建议退回SqlDataReader,但如果你想这样做,你需要这样做

SqlDataReader reader;
try
{
   reader = methodThatReturnsAReader();
}
catch(Exception ex)
{
   // handle the exception
}
finally
{
   // close the reader
   reader.Dispose();
}

更多信息

答案 1 :(得分:2)

只要您确定每次都调用dr.Close()(即使在抛出异常的情况下),那么您的连接也将关闭。但是,通常最好将这种类型的代码包装到try / finally块中,其中finally块包含dr.Close()语句。

另一种选择是using语句,它利用了SqlDataReader实现的IDisposable接口。

答案 2 :(得分:0)

我建议您永远不要从方法返回DataReader。您负责将DataReader关闭到方法调用者。如果方法调用者不能确保DataReader已关闭,即使发生异常,您也会遇到严重问题。

当然,你不应该这样做。

最糟糕的是,在某些情况下,开放的DataReader可以在数据库中创建锁。

唯一的例外是如果方法是私有的,并且您确保所有方法调用者都在关闭DataReader。但它仍然很容易出错。

答案 3 :(得分:0)

围绕using的{​​{1}}语句将保护您,只要它在每个调用SqlDataReader dr = GetMoreData()的地方使用。这很难管理,所以你可以通过改变设计来更好地保护自己。

来自Microsoft Patterns and Practices

“满足以下条件时使用DataSet:

- 您必须在图层之间缓存或传递数据。“

与之相比:

“满足以下条件时使用DataReader:

- 您有一个数据容器,例如可以将数据放入的业务组件。“

我会说你的应用程序有图层,似乎没有使用业务组件。虽然DataSet的开销比DataReader大得多,但请考虑这一点:

  • 泄露连接的成本(高,不可预测)与使用DataSet的成本(可衡量)
  • 您需要多少数据 - 您可以返回GetMoreData()DataTable而不是数据集吗?

DataReader非常适合低级代码,例如数据访问组件,但不应在应用程序的不同部分之间传递。