3

我发现我遇到了一些网站连接池问题,并且正在追踪它们。我知道要寻找的一件事是确保所有 SQLDataReader 都已关闭,但我已经完成并确保它们已关闭。我脑海中突然出现的一个问题是关于返回 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

4 回答 4

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();
}

更多信息

于 2012-05-08T21:42:22.540 回答
2

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

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

于 2012-05-08T21:46:11.760 回答
0

只要在每个被调用的地方都使用该using语句,它就会保护您。这很难管理,因此您可以通过更改设计来更好地保护自己。SqlDataReader dr = GetMoreData()GetMoreData()

来自Microsoft 模式和实践

"当满足以下条件时使用 DataSet:

- 你必须在层之间缓存或传递数据。”

和....相比:

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

——你有一个数据容器,比如一个可以放入数据的业务组件。”

我会说您的应用程序有层并且似乎不使用业务组件。虽然 DataSet 的开销确实比 DataReaders 大得多,但请考虑一下:

  • 泄漏连接的成本(高,不可预测)与使用数据集的成本(可测量)
  • 您需要多少数据 - 您可以返回DataTable还是DataRow代替 DataSet?

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

于 2012-05-08T22:59:28.747 回答
0

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

当然,你不应该这样做。

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

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

于 2012-05-08T22:06:34.917 回答