【问题标题】:Can I avoid the open DataReader exception when using nested commands?使用嵌套命令时可以避免打开 DataReader 异常吗?
【发布时间】:2009-09-01 11:39:28
【问题描述】:

在使用类似这样的构造时,我能否避免打开 DataReader 异常(“已经有一个打开的 DataReader 与此命令关联,必须先关闭。”)?

public void FirstMethod()
{
    using (var command = connection.CreateCommand())
    {
        command.CommandText = "...";
        using (var reader = command.ExecuteReader())
        {
            // do something with the data
            SecondMethod();
        }
    }
}

public void SecondMethod()
{
    using (var command = connection.CreateCommand())
    {
        command.CommandText = "...";
        using (var reader = command.ExecuteReader()) // Exception
        {
        }
    }
}

最好的问候

【问题讨论】:

    标签: c# ado.net datareader


    【解决方案1】:

    您可以使用本地连接(即方法的本地连接);使用连接池,将连接保留为字段的优势是微乎其微的,并且经常会引起这种类型的……乐趣。当然,如果您正在编辑数据,您可能会遇到阻止自己的问题——也许使用TransactionScope 之类的东西可以缓解。底部示例...

    或者,您可以在连接上启用 MARS(多个活动结果集);应该这样做。只需在连接字符串中包含“MultipleActiveResultSets=True”作为一对(SQL Server 2005 及更高版本)。

    public void FirstMethod() {
        using (var connection = CreateAndOpenConnection())
        using (var command = connection.CreateCommand()) {
            command.CommandText = "...";
            using (var reader = command.ExecuteReader()) {
                // do something with the data
                SecondMethod();
            }
        }
    }
    public void SecondMethod() {
        using (var connection = CreateAndOpenConnection())
        using (var command = connection.CreateCommand()) {
            command.CommandText = "...";
            using (var reader = command.ExecuteReader()) // Exception
            { }
        }
    }
    private SqlConnection CreateAndOpenConnection() {
        var conn = new SqlConnection(connectionString);
        conn.Open(); // perhaps dispose if this fails...
        return conn;
    }
    

    【讨论】:

      【解决方案2】:

      为什么不直接更改方法签名?

      public void FirstMethod()
      {
          using (var command = connection.CreateCommand())
          {
              command.CommandText = "...";
              using (var reader = command.ExecuteReader())
              {
                  // do something with the data
                  SecondMethod(reader);
              }
          }
      }
      
      public void SecondMethod(var reader)
      {
          // do stuff with reader...
      }
      

      这不仅避免了这个问题,而且还产生了更少的开销,因为您只创建了 1 个 command/reader 而不是 2 个。(这假设您的方法调用是同步的。)

      另外,考虑使用强类型变量而不是var 关键字;引入var 是为了支持匿名类型,并且只应在必要时使用。

      【讨论】:

      • 好吧,如果第二种方法基于相同的 sql 语句,我会这样做,当然不是这样(否则,我为什么需要方法?)。
      • @Ian:所有变量在 C# 中都是强类型的,但是你声明它们。 (C#4 发布时将允许使用 dynamic 变量,但它们与 var 关键字无关。)
      • 是的,var 关键字只是隐藏了具体类型,但隐含地表示了它。所以你可以写“int i = 1”和“var i = 1”,两个语句是相等的。
      • 阅读器不是“只进”吗?因此,您将无法 // 用阅读器做事...
      • @AMissico:DataReader 可能包含多个结果集。见NextResult方法:msdn.microsoft.com/en-us/library/…
      猜你喜欢
      • 2021-12-04
      • 2020-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-28
      • 2011-05-05
      • 1970-01-01
      • 2015-04-28
      相关资源
      最近更新 更多