我发现,我有一些网站连接池的问题,我跟踪下来的过程。 我知道一件事是寻找,以确保任何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和连接被正确关闭?
谢谢!
描述
该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的方法,使用的应该是int方法的调用者使用。 因此,有没有办法保证的是,DataReader关闭。
我不建议返回一个SqlDataReader
,但如果你想做到这一点,你需要做的
SqlDataReader reader;
try
{
reader = methodThatReturnsAReader();
}
catch(Exception ex)
{
// handle the exception
}
finally
{
// close the reader
reader.Dispose();
}
更多信息
- MSDN - IDisposable接口
- MSDN - SqlDataReader类
只要你确定dr.Close()被调用每次(即使在例外的情况下被抛出),然后是你的连接也将关闭。 然而,这是一般好的做法来包装类型的代码放到一个try / finally块,其中最后一个块包含dr.Close()语句。
另一种方法是使用一个语句,这需要通过SqlDataReader的实施IDisposable接口的优点。
我建议你永远不会从方法返回一个DataReader。 你给关闭的DataReader方法调用者的责任。 如果方法调用者不保证该DataReader关闭,即使发生异常,就会有很大的麻烦。
当然,你不应该做这种方式。
什么是最糟糕的,在某些情况下,一个开放的DataReader可以在数据库中创建锁。
唯一的例外是,如果方法是私有的,你确保所有的调用者都关闭的DataReader。 但它仍然是相当容易出错。
在using
的语句,缠SqlDataReader dr = GetMoreData()
会保护你的,只要它在每一个地方的地方使用GetMoreData()
被调用。 这是难以管理,这样可以更好地通过改变设计来保护自己。
从微软模式与实践 :
“使用时,下列条件为真一个DataSet:
- 你有缓存或层之间传递数据。”
和....相比:
“使用时,下列条件为真一个DataReader:
- 你有一个数据容器,比如一个业务组件,你可以把数据“。
我想说你的应用层并没有出现使用业务组件。 虽然这是事实,数据集有一个比的DataReader更大的开销,可以这样考虑:
- 泄漏的连接(高,不可预测的)与使用数据集的成本的成本(可测量)
- 有多少数据你需要-你可以返回
DataTable
或DataRow
,而不是一个DataSet的?
的DataReader是伟大的低级别的代码,如数据访问组件,但不应该被你的应用程序的不同部分之间传来传去。