数据库
首页 > 数据库> > c# – SqlCommand-SqlConnection使用Disposing问题

c# – SqlCommand-SqlConnection使用Disposing问题

作者:互联网

根据MSDN的IDisposable资源
 嵌套的内部using语句包含外部使用的资源
 声明,嵌套资源的Dispose方法释放了
 包含资源.

MSDN(http://msdn.microsoft.com/en-us/library/ms182334.aspx)=>

Example Nested using statements (Using in Visual Basic) can cause
violations of the CA2202 warning. If the IDisposable resource of the
nested inner using statement contains the resource of the outer using
statement, the Dispose method of the nested resource releases the
contained resource. When this situation occurs, the Dispose method of
the outer using statement attempts to dispose its resource for a
second time. In the following example, a Stream object that is created
in an outer using statement is released at the end of the inner using
statement in the Dispose method of the StreamWriter object that
contains the stream object. At the end of the outer using statement,
the stream object is released a second time. The second release is a
violation of CA2202.

但是,如果我尝试这段代码,代码仍然有效,并返回插入表中的数字计数.这与MSDN解释相矛盾.我希望代码在cmd.ExecuteScalar()调用时崩溃,因为conn变量在第一个内部using语句之后被释放.
为什么这仍然有效,为什么在第一次内部使用后没有配置conn变量?

static void Main(string[] args)
{
    var numbers= DoItGetIt();
}

private static int DoItGetIt()
{
    using (var conn = new SqlConnection("Data Source=BestmixSql;Initial Catalog=Test;Integrated Security=True"))
    {
        conn.Open();
        using (var cmd = new SqlCommand())
        {
            cmd.Connection = conn;
            cmd.CommandText = "INSERT INTO [Test].[dbo].[Tabel] VALUES (666)";
            cmd.ExecuteNonQuery();
        }

        using (var cmd = new SqlCommand())
        {
            cmd.Connection = conn;
            cmd.CommandText = "SELECT COUNT(*) FROM [Test].[dbo].[Tabel]";

            var count = cmd.ExecuteScalar();

            return Convert.ToInt32(count);
        }
    }
}

解决方法:

你正在谈论的MSDN示例是专门讨论内部对象占用外部对象的场景;例如,StreamWriter可以承担Stream的责任.在这种情况下,处理内部对象也会导致外部对象被处置 – 但在一般情况下情况并非如此.

特别是,命令不承担处理连接的责任.有趣的是,数据阅读器可以承担责任,但只能通过可选标志.

许多这样的对象提供标记以让调用者确定内部对象是否应该承担处置外部对象的责任.例如,StreamWriter现在还提供了一个带有bool leaveOpen参数的构造函数重载.如果将其传递为true,则StreamWriter不会级联Dispose().

这是内部对象的所有实现细节,当它专门用于执行此操作时.它不是使用模式的默认行为.

旁注:我会说MSDN在这里完全错了.正确的实现是第一个有两个使用的样本.第二个例子不直观,容易出错.不要使用它.如果有必要,使用leaveOpen来制作是明确的,但坦率地说,没有这个,它通常可以正常工作,如果您无论如何要处理它.

标签:c,dispose,using-statement
来源: https://codeday.me/bug/20190703/1365874.html