我发现我遇到了一些网站连接池问题,而我正在跟踪它们。我知道有一件事要确保任何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和连接是否正确关闭?
谢谢!
答案 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大得多,但请考虑这一点:
GetMoreData()
或DataTable
而不是数据集吗?DataReader非常适合低级代码,例如数据访问组件,但不应在应用程序的不同部分之间传递。