【问题标题】:Disposing SqlCommand处理 SqlCommand
【发布时间】:2018-08-21 22:10:08
【问题描述】:

因为SqlCommand 实现IDisposable,我通常会按如下方式处理ADO 查询。

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
{
    // Execute command, etc. here
}

但是,如果我需要在单个连接期间执行多个命令怎么办?我真的需要为每个命令创建一个新的using 块吗?

我从 Microsoft 找到的示例没有为 SqlCommands 使用 using 块(甚至调用 Dispose())。处置SqlCommand 的最佳做法是什么?

【问题讨论】:

  • 如果您不需要重叠访问,没有理由不重用单个 SqlCommand。
  • 我个人对连接块内的每个命令对象都使用了一个新的 using 块。您也可以随时重置命令信息并清除参数并使用现有命令对象运行新查询。

标签: c# ado.net idisposable sqlconnection sqlcommand


【解决方案1】:

当然,最佳做法是丢弃它们。

using (SqlConnection connection = new SqlConnection(connectionString))
{
   connection.Open();

   using (SqlCommand command1 = new SqlCommand(query1, connection))
   {
      // Execute command, etc. here
   }

   using (SqlCommand command2 = new SqlCommand(query2, connection))
   {
      // Execute command, etc. here
   }

   using (SqlCommand command3 = new SqlCommand(query3, connection))
   {
      // Execute command, etc. here
   }
}

MSDN 可能不会显示它,因为在 SqlCommand 的情况下它是 not really needed。但在我看来,微软不在每个实现IDdisosable 的对象上使用这种模式是很糟糕的,因为人们不习惯它。

【讨论】:

  • 好的,我可以看到这是最彻底的最佳实践。但我想知道如果 Microsoft 的示例不这样做,有多少人实际上在这样做?
  • @JonathanWood:我已经编辑了我的答案,确切地提到了这一点
【解决方案2】:

using 语句可确保调用 Dispose,即使在您调用对象上的方法时发生异常也是如此。您可以通过将对象放在 try 块中,然后在 finally 块中调用 Dispose 来获得相同的结果。

在这种情况下,您对每个命令块使用using

using (SqlConnection connection = new SqlConnection(connectionString))
{
   using (SqlCommand cmd1= new SqlCommand(query1, connection))
   {
   }

   using (SqlCommand cmd2= new SqlCommand(query2, connection))
   {
   }  
}

【讨论】:

    【解决方案3】:

    不,你没有。有两种方法可以将您的多个命令捆绑在一个连接和命令中。

    第一种是重用现有的 CMD 对象,但根据需要更改 CommandText 和其他 CMD.properties。

    using (SqlConnection con = new SqlConnection(connectionString)) {
    
        con.Open();
    
        using (SqlCommand cmd = new SqlCommand(query1, con)) {
            // cmd.CommandType = CommandType.xxxxx
            // add any parameters
            // Execute()
    
            cmd.CommandText = query2;
            // reset CommandType if needed
            // adjust parameters if needed
            // Execute()
    
            cmd.CommandText = query 3;
            // reset CommandType if needed
            // adjust parameters if needed
            // Execute()
        }
        con.Close();
    }
    

    第二种方法是在数据库服务器上创建一个存储过程并在一个 CMD 对象中调用它

    -- Database
    CREATE PROCEDURE schema.sproc_CommandBatch (
        -- any variables here
    ) AS
    BEGIN
        -- query 1
    
        -- query 2
    
        -- query 3
    END
    GO
    
    
    // C#
    using (SqlConnection con = new SqlConnection(connectionString)) {
    
        con.Open();
    
        using (SqlCommand cmd = new SqlCommand("schema.sproc_CommandBatch", con)) {
            // cmd.CommandType = CommandType.StoredProcedure
            // add any parameters
            // Execute()
        }
        con.Close();
    }
    

    【讨论】:

      【解决方案4】:

      最佳实践是,如果它实现 IDisposable 然后 Dispose() 它。 事实上,here 的例子都调用了 Dispose。有皱纹:

      第一个示例,它打开一个 SqlDataReader,在 finally 子句中的命令上调用 .Close()。事实上, .Close 只是 .Dispose() 的一个包装器(并且不再出现在文档中)。 乔纳森伍德在他的评论中指出,收盘价在读者身上。这是错误的。

      对于同一连接上的多个呼叫,您可以:

      1. 重复使用 one 命令(在 one using 中声明)。我不喜欢这个 我自己,但那只是我:我觉得它...丑陋。
      2. 在多次使用中使用多个命令。这就是我要做的。

      “最佳实践”有点模糊。从来没有一致同意 A 吹捧的最佳实践比 B 推荐的更好,更不用说 C、D 或 E。请自行判断。

      【讨论】:

      • 第一个示例在阅读器上调用 close,而不是连接。我并不是说它们不存在,但我还没有查看 Microsoft 的示例,其中在 SqlCommand 上调用了 Dispose()
      • @JonathanWood - 很好,很抱歉错过了这一点。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-12
      • 2013-11-10
      • 1970-01-01
      • 2015-12-06
      • 1970-01-01
      • 1970-01-01
      • 2012-09-11
      相关资源
      最近更新 更多