Skip to content

Instantly share code, notes, and snippets.

@bdukes
Created March 16, 2011 18:58
Show Gist options
  • Save bdukes/873080 to your computer and use it in GitHub Desktop.
Save bdukes/873080 to your computer and use it in GitHub Desktop.
The DataReaderEnumerable is a simple class that wraps an IDataReader and implements IEnumerable<IDataReader>. This allows all of the LINQ methods to be used on an IDataReader.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.CodeAnalysis;
/// <summary>
/// Enumerates over an <see cref="IDataReader"/> instance, moving to the next record upon each enumeration.
/// </summary>
/// <remarks>
/// Based on http://codecisions.com/post/2010/04/08/Enumerating-IDataReader-With-LINQ.aspx
/// Stored on https://gist.github.com/873080
/// </remarks>
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification = "DataReaderCollection isn't really an accurate name")]
public class DataReaderEnumerable : IEnumerable<IDataReader>, IDisposable
{
/// <summary>
/// Whether the <see cref="DataReader"/> has been enumerated before
/// </summary>
private bool enumerated;
/// <summary>
/// Initializes a new instance of the <see cref="DataReaderEnumerable"/> class.
/// </summary>
/// <param name="dataReader">The data reader to enumerate.</param>
public DataReaderEnumerable(IDataReader dataReader)
{
this.DataReader = dataReader;
}
/// <summary>
/// Gets the data reader being enumerated.
/// </summary>
public IDataReader DataReader { get; private set; }
/// <summary>
/// Returns an enumerator that iterates through the <see cref="DataReader"/>.
/// </summary>
/// <returns>
/// <returns>An <see cref="IEnumerable{T}"/> instance that can iterate over the rows in the <see cref="DataReader"/></returns>
/// </returns>
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IDataReader", Justification = "IDataReader is spelled correctly")]
public IEnumerator<IDataReader> GetEnumerator()
{
if (this.enumerated)
{
throw new InvalidOperationException("The IDataReader can only be enumerated once.");
}
this.enumerated = true;
return this.GetEnumeratorImpl();
}
/// <summary>
/// Disposes the <see cref="DataReader"/>.
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="IEnumerator"/> object that can be used to iterate through the collection.
/// </returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
/// <summary>
/// Disposes the <see cref="DataReader"/>.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (this.DataReader != null)
{
this.DataReader.Dispose();
this.DataReader = null;
}
}
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="IEnumerable{T}"/> instance that can iterate over the rows in the <see cref="DataReader"/>
/// </returns>
private IEnumerator<IDataReader> GetEnumeratorImpl()
{
using (this.DataReader)
{
while (this.DataReader.Read())
{
yield return this.DataReader;
}
}
}
}
using System.Data;
public static class Extensions
{
/// <summary>
/// Wraps the <paramref name="dataReader"/> in a <see cref="DataReaderEnumerable"/>.
/// </summary>
/// <param name="dataReader">The data reader to wrap.</param>
/// <returns>A <see cref="DataReaderEnumerable"/> instance wrapping the <paramref name="dataReader"/></returns>
public static DataReaderEnumerable AsEnumerable(this IDataReader dataReader)
{
return new DataReaderEnumerable(dataReader);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment