Pregunta

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!

¿Fue útil?

Solución

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

Otros consejos

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();
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top