实现IDbConnection
,IDbCommand
和IDataReader
的数据库访问类都实现IDisposable
,但显然Command和Reader依赖于Connection。我的问题是,我是否必须单独处理每个这些对象的Dispose(),还是处理其他对象的Connection对象?
也就是说,我可以这样做并保证我不会冒任何未被释放的非托管资源的风险:
using (IDbConnection conn = GetConnection())
{
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = " ..... ";
IDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
}
}
或者我必须这样做:
using (IDbConnection conn = GetConnection())
{
using (IDbCommand cmd = conn.CreateCommand())
{
cmd.CommandText = " ..... ";
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
}
}
}
}
或者这个实现是依赖的,所以它可能使用一个数据库的提供者但不能用于另一个数据库吗?
答案 0 :(得分:4)
最佳策略是使用块中的所有ADO.NET对象 - 完全停止。
对各种ADO.NET对象的一点反射显示,如果没有关闭/处置,事情会或多或少地掉在地板上。这种影响很大程度上取决于你正在使用哪些提供商 - 如果你使用的是非托管句柄(ODBC,OleDb等),你可能会泄漏内存,因为我没有看到任何东西在终结者的方式。如果它是一个全托管的提供者(例如,SqlClient),它最终会得到清理,但是根据你所持有的对象,你最终可能会在数据库服务器上保留的资源比你想要的要长很多
答案 1 :(得分:1)
您应该单独处理它们,或者您也可以使用提供here的解决方案。
答案 2 :(得分:1)
单独处理它们。 Reader和Command对象完全可能在其dispose例程中执行更多操作,而不仅仅是破坏连接(现在或将来的ADO.NET版本)。因此,为了(a)明确和(b)安全,你应该单独处理它们。
他们实现IDisposable的事实表明你应该在完成对象时总是运行Dispose例程,所以最好不要尝试再次猜测界面,它不会给你任何好处,而你可能最终会泄漏记忆和处理。
在嵌套using
语句时,您可以做一些事情来使代码看起来更干净。例如:
(using SqlConnection conn = new SqlConnection())
(using SqlCommand comm = new SqlCommand())
{
//Do stuff
}
看起来比(在我看来)更整洁,而不是嵌套。
答案 3 :(得分:0)
你应该单独处理它们。即使处置IDbConnection会将所有内容都置于封面(我不知道它是否确实存在,我也不关心,因为接下来的原因),你应该在将来时编程。明天有人会编辑该代码并在同一个连接上发出一个新命令,然后它会想知道为什么他会收到一个连接仍然在使用的错误(因为IDataReader没有被处理掉)。
答案 4 :(得分:0)
using语句的主要优点是资源发布管理。通常,.NET Framework垃圾收集器控制资源分配和释放。使用using语句,我们可以控制它。因此,using语句实现了一个IDisposible接口,该接口包含一个公共的Dispose()方法。
您也可以手动调用Dispose()方法从内存中释放资源或对象。
希望这会有所帮助。