Question

Actually it doesn't have to be an IDataReader.

I had a function something like this:

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

This was working fine until I refactored it like so:

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

This doesn't work because when the CloseDBConnections() is executed the enumeration has not yet been processed.

Calling .ToList() on the return from GetObjects is what actually executes the enumeration but by then the connection has already been destroyed and the IDataReader fails.

In my instance CloseDBConnections cannot be called from within the new ProcessReader function because the IDataReader could have come from some other source (the whole point of re-factoring in this instance)

Is there a sensible workaround for this or will I have to duplicate the enumerating code?

I tried putting the call to ProcessReader as yield return instead of return but this doesn't work because C# (understandably) thinks I am trying to add an IEnumerable to the IEnumerable!

Was it helpful?

Solution

How about calling CloseDBConnections in ProcessReader via a callback?

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

OTHER TIPS

Not pretty, but this should work.

public IEnumerable<MyClass> GetObjects() 
{
  IDataReader dr = GetSomeDataReader();
  try
  {
    foreach (var result in ProcessReader(dr))
    {
      yield return result;
    }
  } finally {
    CloseDBConnections();
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top