Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiom for using SqlDataReader as a resource

Following on from this question, I find myself writing the following code over and over again:

SqlCommand command = new SqlCommand();
// Code to initialize command with what we want to do
using (SqlConnection connection = openConnection())
{
    command.Connection = connection;
    using (SqlDataReader dataReader = thisCommand.ExecuteReader())
    {
        while (dataReader.Read())
        {
            // Do stuff with results
        }
    }
}

It's rather tedious to have to nest the two using statements. Is there a way to tell SqlDataReader that it owns the command, and tell the command that it owns the connection?

If there was a way of doing that then I could write a helper method which could be called like so:

// buildAndExecuteCommand opens the connection, initializes the command
// with the connection and returns the SqlDataReader object. Dispose of the
// SqlDataReader to dispose of all resources that were acquired
using(SqlDataReader reader = buildAndExecuteCommand(...))
{
    // Do stuff with reader
}

Or do I have to bite the bullet and write my own wrapper over SqlDataReader?

like image 915
Paul Hollingsworth Avatar asked Jan 23 '23 11:01

Paul Hollingsworth


1 Answers

One thing would be to write a method which did the disposal for you, calling back into a delegate with each result. For example:

using (SqlConnection connection = openConnection())
{
    command.Connection = connection;
    ExecuteReaderWithCommand(command, reader =>
    {
        // Do stuff with the result here.
    });
}

Then ExecuteReaderWithCommand would be something like:

public static void ExecuteReaderWithCommand(SqlCommand command,
    Action<SqlDataReader> action)
{
    using (SqlDataReader dataReader = thisCommand.ExecuteReader())
    {
        while (reader.Read())
        {
            action(reader);
        }
    }
}

You could make this an extension method on SqlCommand if you wanted to. Heck, you could go to town and make it open the connection for you as well if you wanted... the more you can abstract away the idea of "open / use / close", the better.

like image 75
Jon Skeet Avatar answered Jan 29 '23 10:01

Jon Skeet