[英]Is it correct to not dispose of SqlCommand like the example in Microsoft documentation?
SqlCommand 类的 Microsoft 文档提供了以下示例代码,它不处理 SqlCommand。
SqlCommand 继承自实现 IDisposable 的 DbCommand。
常识表明建议处置 SqlCommand,但是,该示例没有。
该示例是否提供了最佳实践?
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(
queryString, connection);
connection.Open();
using(SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
}
}
首先在您的代码中查看我的评论
private static void ReadOrderData(string connectionString)
{
string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
connection.Open();
using(SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}", reader[0], reader[1]));
}
} // -- disposes reader and closes connection
} // -- disposes connection and closes it
}
command
在连接范围内声明了using
,即try/catch/finally
命令不一定持有连接之外的任何资源。 并且您正在处理连接,该连接在处理阅读器时已经关闭。 (请参阅CommandBerhavior
)。 因此,最后, command
是保存对已处置资源的引用的对象。
为了更好地了解,请使用一些反射工具并查看内部。
protected override void Dispose(bool disposing)
{
if (disposing)
this._cachedMetaData = (_SqlMetaDataSet) null;
base.Dispose(disposing);
}
那么,这个元数据是什么? 可能是一些参数信息。 但是,如果您不添加参数,那么您可能没有什么可处置的。 Microsoft 知道这一点,并发现没有必要在command
中包含dispose
。 这是为了回答,为什么微软不包括using
for command
。
看构造函数
public SqlCommand()
{
GC.SuppressFinalize((object) this);
}
看起来一开始就没有什么可处置的。 所有这些“缓存的项目”都将正常进行垃圾收集。 我在那里没有找到任何 IO 或其他非托管资源。
但是,要记住的一件事是,实现可能会因版本而异,而您不想更改代码。 因此,在命令中添加另一层
private static void ReadOrderData(string connectionString)
{
string queryString = "SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(queryString, connection))
{
. . . . . .
}
}
这可能会节省一些麻烦。
有趣的事实:当使用实现与SqlClient
相同的接口和基类的MySql
提供程序时, MySqlCommand.Dispose
中存在一个错误(可能仍然存在),它总是关闭读者。 与using
相同的代码适用于 SqlClient 和 Oracle ODP,但不适用于 MySql。 我必须包装MySqlCommand
并在与提供程序无关的代码中使用我的自定义类(想想装饰器模式)来覆盖行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.