Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

foreach with SqlDataReader?

Tags:

c#

I have the following code:

SqlDataReader reader = getAddressQuery.sqlReader;
while (reader.Read())
{
    foreach (Object ob in reader)
    {
        someText.InnerText = someText.InnerText + " " + ob.ToString();
    }
}

The code in the foreach loop does not execute. However, I can do this:

SqlDataReader reader = getAddressQuery.sqlReader;
while (reader.Read())
{
    someText.InnerText = reader[0].ToString();
}

Which works.

Obviously I could achieve the same result using a regular for loop rather than a foreach loop, but I think the foreach syntax is clearer, so I use it when possible.

What has gone wrong here? Are foreach loops in c# not as flexible as in more high level languages?

like image 412
Oliver Avatar asked Aug 18 '11 10:08

Oliver


People also ask

What is the use of SqlDataReader?

The ADO.NET SqlDataReader class in C# is used to read data from the SQL Server database in the most efficient manner. It reads data in the forward-only direction. It means, once it read a record, it will then read the next record, there is no way to go back and read the previous record.

How do I get data from ExecuteReader?

To retrieve data using a DataReader, create an instance of the Command object, and then create a DataReader by calling Command. ExecuteReader to retrieve rows from a data source.

What is ExecuteReader in C#?

The ExecuteReader() in C# SqlCommand Object sends the SQL statements to the Connection Object and populate a SqlDataReader Object based on the SQL statement. When the ExecuteReader method in SqlCommand Object execute , it will instantiate a SqlClient.


1 Answers

Something like the following. Note that IDataReader derives from IDataRecord which exposes the members used to process the current row:

IEnumerable<IDataRecord> GetFromReader(IDataReader reader)
{
    while(reader.Read()) yield return reader;
}

foreach(IDataRecord record in GetFromReader(reader))
{
    ... process it ...
}

Or even something like the following, to get an enumeration or list of strongly-typed entity objects from a reader:

IEnumerable<T> GetFromReader<T>(IDataReader reader, Func<IDataRecord, T> processRecord)
{
    while(reader.Read()) yield return processRecord(reader);
}

MyType GetMyTypeFromRecord(IDataRecord record)
{
    MyType myType = new MyType();
    myType.SomeProperty = record[0];
    ...
    return myType;
}

IList<MyType> myResult = GetFromReader(reader, GetMyTypeFromRecord).ToList();

UPDATE in response to Caleb Bell's comment.

I agree Enumerate is a better name.

In fact in my personal "common" library, I've now replaced the above by an extension method on IDataReader:

public static IEnumerable<IDataRecord> Enumerate(this IDataReader reader)
{
    while (reader.Read())
    {
        yield return reader;
    }
}

And the caller can get strongly-typed objects using:

reader.Enumerate.Select(r => GetMyTypeFromRecord(r))
like image 155
Joe Avatar answered Sep 18 '22 18:09

Joe