繁体   English   中英

不像 Microsoft 文档中的示例那样处理 SqlCommand 是否正确?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM