c# - SqlCommand-SqlConnection 使用处置问题

标签 c# dispose using-statement

根据 MSDN 如果 IDisposable 资源的 嵌套的内部 using 语句包含外部 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()

这是内部对象的所有实现细节,专门为此编写。这不是 using 模式的默认行为。


旁注:我想说 MSDN 在这里完全是错误的。 正确的 实现是第一个有两个using 的示例。第二个示例是不直观的,并且容易出现不正确的实现。不要使用它。如有必要,请使用 leaveOpen 进行显式处理,但坦率地说,如果您无论如何都打算处理它,它通常在没有它的情况下也能正常工作。

关于c# - SqlCommand-SqlConnection 使用处置问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21783907/

相关文章:

c# - 确定性处理 ThreadStatic 对象

c# - 调用 Clear 是否也会处理这些项目?

c# - 如何在 ASP.NET 应用程序中使用 SQL Server CE

c# - IEnumerable <T>的实现适用于foreach,但不适用于LINQ

c# - 允许消除 lambda 表达式中的参数的技术名称是什么?

c# - 多次处理对象

c# - 为什么在 using 语句中声明的变量被视为只读?

c# - 我可以将 using() {} block 与方法的 out 参数结合使用吗?

c# - 使用语句实现与 C# 等效的 C++

c# - 使用 Selenium 3 启动特定的 Firefox 配置文件