如何在ADO.NET对象上调用Dispose?
实现IDbConnection
,IDbCommand
和IDataReader
的数据库访问类都实现IDisposable
,但很明显,命令和读者都依赖于连接上。我的问题是,我必须单独Dispose()每个这些对象还是将处置Connection对象处置其他对象?如何在ADO.NET对象上调用Dispose?
也就是说,我能做到这一点,并保证我不会冒着留下任何非托管资源不被释放:
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())
{
}
}
}
}
或者这个实现是依赖的,所以它可能会使用一个数据库的提供者,但不适用于其他的?
最好的策略是使用所有ADO.NET对象中的使用块 - 句号。
稍微反映一下各种ADO.NET对象,表明如果不关闭/处置,事情或多或少会落在地板上。这样做的效果将取决于你正在使用哪些提供程序 - 如果你正在使用下面的非托管句柄(ODBC,OleDb等),你可能会泄漏内存,因为我什么也没有看到在终结者的方式。如果它是一个全能管理的提供者(例如SqlClient),它最终会得到清理,但取决于你所持有的对象,最终可能会在数据库服务器上使用比您想要的更长的资源。
单独处置它们。 Reader和Command对象完全有可能在其处理例程中执行更多的操作,而不仅仅是破坏连接(现在或将来的ADO.NET版本)。所以为了(a)要明确,并且(b)要安全,你应该单独处理它们。
它们实现IDisposable的事实表明,当你完成对象时,你应该总是运行Dispose例程,所以最好不要尝试和猜测接口,它不会给你带来任何好处,并且你可能最终会泄漏内存和句柄。
虽然在嵌套using
语句时可以使代码看起来更清晰,但您仍可以执行某些操作。例如:
(using SqlConnection conn = new SqlConnection())
(using SqlCommand comm = new SqlCommand())
{
//Do stuff
}
这看起来比嵌套牙套更整洁(在我看来)。
您应该单独处置它们。即使处置IDbConnection会将所有内容处理掉(我不知道它是否真的存在,我也不关心,因为后面的原因),您应该按将来时间进行编程。明天有人会编辑该代码并在同一连接上发出一个新命令,然后它会问他为什么会收到连接仍在使用中的错误(因为IDataReader没有处理)。
使用语句的主要优点是资源释放管理。通常,.NET Framework垃圾收集器控制资源分配和释放。通过使用声明,我们可以控制它。因此,using语句实现了一个包含公共Dispose()方法的IDisposible接口。
此外,您也可以始终手动调用Dispose()方法以释放内存中的资源或对象。
希望这有助于。