在收益率返回完成后关闭IDataReader

本文关键字:IDataReader 收益率 返回 | 更新日期: 2023-09-27 18:24:45

实际上它不必是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

在收益率返回完成后关闭IDataReader

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();
  }
}

虽然不漂亮,但应该可以。

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