Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关闭SQLDataReaders-如何判断它们是否已关闭?_C#_Database Connection_Connection Pooling_Sqldatareader - Fatal编程技术网

C# 关闭SQLDataReaders-如何判断它们是否已关闭?

C# 关闭SQLDataReaders-如何判断它们是否已关闭?,c#,database-connection,connection-pooling,sqldatareader,C#,Database Connection,Connection Pooling,Sqldatareader,我发现我有一些网站连接池的问题,我在跟踪他们的过程中。我知道要寻找的一件事是确保任何SQLDataReader都被关闭,我已经检查并确保它们被关闭。我脑海中突然出现的一个问题是关于返回SQLDataReaders的方法以及它们如何关闭(或不关闭) 下面是我如何进行设置和一些示例方法: public static SqlDataReader ExecuteReader(SqlCommand cmd) { SqlConnection c = new SqlConnection(Propert

我发现我有一些网站连接池的问题,我在跟踪他们的过程中。我知道要寻找的一件事是确保任何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()的方法”

现在假设我有另一个调用“GetData”的方法。我显然简化了事情

public static SqlDataReader GetMoreData()
{
  return GetData;
}
所以我的问题是,当我像这样调用“GetMoreData”时

SqlDataReader dr = GetMoreData();
//do some stuff with 'dr'
dr.close();
我所有的SqlDataReader和连接都正确关闭了吗

谢谢

描述
SqlDataReader
实现了
IDisposable
接口。 在每个实现了
IDisposable
的类上,您应该调用
Dispose
或使用
using
为了释放资源,在本例中关闭读卡器和底层连接

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

样品

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();
}
更多信息

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


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

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

当然,你不应该这样做。

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


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

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

发件人:

“在下列条件为真时使用数据集:

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

与之相比:

“当下列条件为真时,使用数据读取器:

-您有一个数据容器(如业务组件),可以将数据放入其中。”

我想说的是,您的应用程序有层次,似乎没有使用业务组件。虽然数据集比数据存储器有更大的开销,但请考虑如下:

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

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

您说“全部”,但您只有一个阅读器和一个连接。从你的代码来看,如果没有抛出异常,当读卡器关闭时,这两个部分都应该关闭。如果你的
//使用'dr'执行一些操作
部分抛出异常,那么,不,你的读卡器没有正确关闭。dknaack的回答通过告诉您使用
using
语句修复了这个bug。我发现您使用的是静态函数。在实际代码中不使用任何静态字段来放置读取器或连接,是吗?是的,这是正确的,但如果他实现了一个返回DataReader的方法,则应该在该方法的调用方中使用using。因此,无法保证DataReader已关闭。这是一个设计缺陷!
SqlDataReader dr;
try
{   
    dr = GetMoreData();
    // do your stuff
}
catch(Exception ex)
{
   // handle the exception
}
finally
{
   // close the reader
   dr.Dispose();
}
SqlDataReader reader;
try
{
   reader = methodThatReturnsAReader();
}
catch(Exception ex)
{
   // handle the exception
}
finally
{
   // close the reader
   reader.Dispose();
}