【问题标题】:Closing an IDataReader after yield return is completeyield return 完成后关闭 IDataReader
【发布时间】:2013-07-25 08:33:28
【问题描述】:

其实不一定是IDataReader

我有一个类似这样的函数:

public IEnumerable<MyClass> GetObjects() 
{
  IDataReader dr = GetSomeDataReader();
  while (dr.Read())
  {
    yield return new MyClass(dr);
  }
  CloseDBConnections();
}

在我像这样重构它之前,这一切正常:

public IEnumerable<MyClass> GetObjects() 
{
  IDataReader dr = GetSomeDataReader();
  try
  {
    return ProcessReader(dr);
  } finally {
    CloseDBConnections();
  }
}
public IEnumerable<MyClass> ProcessReader(IDataReader dr)
{
  while (dr.Read())
  {
    yield return new MyClass(dr);
  }
}

这不起作用,因为在执行CloseDBConnections() 时,尚未处理枚举。

在从GetObjects 返回时调用.ToList() 是实际执行枚举的操作,但到那时连接已经被破坏并且IDataReader 失败。

在我的实例中,CloseDBConnections 不能从新的 ProcessReader 函数中调用,因为 IDataReader 可能来自其他来源(在此实例中重构的重点)

对此是否有合理的解决方法,或者我是否必须复制枚举代码?

我尝试将ProcessReader 调用为yield return 而不是return,但这不起作用,因为C#(可以理解)认为我正在尝试将IEnumerable 添加到IEnumerable

【问题讨论】:

    标签: c# ienumerable yield-return


    【解决方案1】:

    通过回调在ProcessReader 中调用CloseDBConnections 怎么样?

    public IEnumerable<MyClass> GetObjects() 
    {
      return ProcessReader(GetSomeDataReader(), CloseDBConnections);
    }
    
    public IEnumerable<MyClass> ProcessReader(IDataReader dr, Action OnFinished)
    {
      try
      {
        while (dr.Read())
          yield return new MyClass(dr);
      }
      finally
      {
        if (OnFinished != null) 
          OnFinished();
      }
    }
    

    【讨论】:

    • 您应该在finally 中执行回调。否则,如果迭代提前完成(例如GetObjects().First()),它将不会被执行。
    • @DominicKexel 我喜欢它。这就是我最终在 Javascript 中做很多事情的方式
    • @svick 我不知道这一点 - 我想这意味着原始代码应该有相同的尝试/最终出于相同的原因。
    • @DJL 是的,你是对的,finally 也是必要的。
    【解决方案2】:

    不漂亮,但这应该可以。

    public IEnumerable<MyClass> GetObjects() 
    {
      IDataReader dr = GetSomeDataReader();
      try
      {
        foreach (var result in ProcessReader(dr))
        {
          yield return result;
        }
      } finally {
        CloseDBConnections();
      }
    }
    

    【讨论】:

    • 是的,我确实考虑过这一点。我希望有一个更清洁的解决方案(比如一些神奇的关键字或其他东西)。在这种情况下,如果上述解决方案是唯一可能的解决方案,那么重新分解似乎并不值得。我想我可能希望太多了!
    猜你喜欢
    • 2012-09-30
    • 2017-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 2017-02-27
    相关资源
    最近更新 更多