5

I have a lot of existing code which uses raw ADO.NET (DbConnection, DbDataReader, etc). I would like to transition to using LINQ to SQL for new code, but for now put both the existing and new code behind a unified set of Repository classes.

One issue I have is this: I would like the Repository classes to expose result sets as IQueryable<> which I get for free with LINQ to SQL. How do I wrap my existing DbDataReader result sets in an IQueryable? Do I have to implement IQueryable over DbDataReader from scratch?

Note I am aware of LINQ to DataSet, but I don't use DataSets because of memory scale issues, as the result sets I deal with can be quite large (order of 1000s). This implies that the IQueryable over DbDataReader implementation will need to be efficient as well (i.e. don't cache results in memory).

dso
  • 9,463
  • 10
  • 53
  • 59
  • Re your comment - one option (that still preserves laziness etc) is `Select` - i.e. reader.AsEnumerable().Select(record => BuildPerson(record)) etc - which gives you an IEnumerable – Marc Gravell Jun 25 '09 at 07:13
  • Nice... and my helper class is generic so it would look something like: reader.AsEnumerable().Select(record => RecordToObject(record)) – dso Jun 25 '09 at 07:31

1 Answers1

7

I can't see any benefit in implement IQueryable<T> - that suggests more functionality than is actually available - however, you could implement it as an IEnumerable<T> easily enough, with the caveat that it is once-only. An iterator block would be a reasonable choice:

    public static IEnumerable<IDataRecord> AsEnumerable(
        this IDataReader reader)
    {
        while (reader.Read())
        {
            yield return reader; // a bit dangerous
        }
    }

The "a bit dangerous" is because the caller could cast it back and abuse it...

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Great, I think you're right, I should expose IEnumerable instead of IQueryable. Also, I already have a utility function which populates an object's properties from IDataRecord column values (using reflection), so I can return entity objects instead of IDataRecord from the Repository methods. Thanks – dso Jun 24 '09 at 23:31
  • This worked great with LINQ. DbDataReader reader = stmt.ExecuteReader(); // Add some WHERE predicate here var rows = from _row in reader.AsEnumerable() select _row; // Iterate the rows foreach (var row in rows) – John Jesus Aug 14 '14 at 21:50