Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using yield to iterate over a datareader might not close the connection?

Tags:

yield

.net-2.0

Here is a sample code to retrieve data from a database using the yield keyword that I found in a few place while googling around :

public IEnumerable<object> ExecuteSelect(string commandText)
{
    using (IDbConnection connection = CreateConnection())
    {
        using (IDbCommand cmd = CreateCommand(commandText, connection))
        {
             connection.Open();
             using (IDbDataReader reader = cmd.ExecuteReader())
             {
                while(reader.Read())
                {
                    yield return reader["SomeField"];
                }
             }
             connection.Close();
        }
    }
}

Am I correct in thinking that in this sample code, the connection would not be closed if we do not iterate over the whole datareader ?

Here is an example that would not close the connection, if I understand yield correctly..

foreach(object obj in ExecuteSelect(commandText))
{
  break;
}

For a db connection that might not be catastrophic, I suppose the GC would clean it up eventually, but what if instead of a connection it was a more critical resource?

like image 763
Joel Gauvreau Avatar asked Sep 06 '08 14:09

Joel Gauvreau


2 Answers

The Iterator that the compiler synthesises implements IDisposable, which foreach calls when the foreach loop is exited.

The Iterator's Dispose() method will clean up the using statements on early exit.

As long as you use the iterator in a foreach loop, using() block, or call the Dispose() method in some other way, the cleanup of the Iterator will happen.

like image 145
Douglas Leeder Avatar answered Oct 12 '22 12:10

Douglas Leeder


Connection will be closed automatically since you're using it inside "using" block.

like image 42
aku Avatar answered Oct 12 '22 11:10

aku