MSDN Documentation

ADO.NET DataReaders

ADO.NET DataReader classes provide a high-performance, forward-only, read-only stream of data from a data source. They are ideal for scenarios where you need to read a large number of records efficiently without loading the entire dataset into memory.

Understanding DataReaders

The primary classes for data reading in ADO.NET are:

These classes implement the abstract DbDataReader class, providing a consistent interface for accessing data.

Key Features and Benefits:

Working with DataReaders

The basic workflow for using a DataReader involves:

  1. Opening a database connection.
  2. Creating a command object.
  3. Executing the command using ExecuteReader(), which returns a DataReader.
  4. Iterating through the rows using a while (reader.Read()) loop.
  5. Accessing column values within the loop.
  6. Closing the DataReader and the connection.

Example: Using SqlDataReader

The following C# example demonstrates how to retrieve data using SqlDataReader:


using System;
using System.Data;
using System.Data.SqlClient;

public class DataReaderExample
{
    public static void ReadProducts(string connectionString)
    {
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            string query = "SELECT ProductID, ProductName, UnitPrice FROM Products";
            using (SqlCommand command = new SqlCommand(query, connection))
            {
                try
                {
                    connection.Open();
                    using (SqlDataReader reader = command.ExecuteReader())
                    {
                        if (reader.HasRows)
                        {
                            while (reader.Read())
                            {
                                // Access data by column name or ordinal index
                                int productId = reader.GetInt32(reader.GetOrdinal("ProductID"));
                                string productName = reader.GetString(reader.GetOrdinal("ProductName"));
                                decimal unitPrice = reader.GetDecimal(reader.GetOrdinal("UnitPrice"));

                                Console.WriteLine($"ID: {productId}, Name: {productName}, Price: {unitPrice:C}");
                            }
                        }
                        else
                        {
                            Console.WriteLine("No rows found.");
                        }
                    } // DataReader is automatically closed here
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"An error occurred: {ex.Message}");
                }
            } // Command object is disposed here
        } // Connection is automatically closed here
    }

    public static void Main(string[] args)
    {
        // Replace with your actual connection string
        string connString = "Server=myServerAddress;Database=myDatabase;User Id=myUsername;Password=myPassword;";
        ReadProducts(connString);
    }
}
            

Accessing Column Data

You can retrieve data from columns in several ways:

Handling Null Values

Always check for DBNull.Value before attempting to retrieve a value that might be NULL.


if (!reader.IsDBNull(reader.GetOrdinal("Description")))
{
    string description = reader.GetString(reader.GetOrdinal("Description"));
    Console.WriteLine($"Description: {description}");
}
else
{
    Console.WriteLine("Description: N/A");
}
            

Common DataReader Methods

Method Description
Read() Advances the DataReader to the next record. Returns true if there are more rows, false otherwise.
Close() Closes the DataReader object.
FieldCount Gets the number of columns in the current row.
GetName(ordinal) Gets the name of the specified column.
GetOrdinal(name) Gets the column ordinal (index) of the specified column.
IsDBNull(ordinal) Indicates whether the specified column contains null values.
GetInt32(ordinal) Retrieves the value of the specified column as a 32-bit signed integer.
GetString(ordinal) Retrieves the value of the specified column as a string.
GetDecimal(ordinal) Retrieves the value of the specified column as a decimal.
GetDateTime(ordinal) Retrieves the value of the specified column as a DateTime object.
GetValue(ordinal) Retrieves the value of the specified column as a boxed object.

Note on Resource Management

Always ensure that DataReader and Connection objects are properly closed or disposed of, typically using using statements in C#, to release database resources promptly.

Performance Tip

When you only need a subset of columns, specify them explicitly in your SQL query rather than using SELECT * to minimize data transfer and processing.

When to Use DataReaders

For scenarios requiring offline data manipulation, complex filtering, or data binding to UI controls without a live connection, DataSet or DataTable might be more appropriate.