Microsoft Docs

Working with DataReaders in ADO.NET

DataReaders, specifically the DataReader classes within ADO.NET, provide a forward-only, read-only stream of data from a data source. This makes them highly efficient for retrieving large datasets when you only need to process the data sequentially.

Understanding DataReaders

The core principle behind a DataReader is its ability to fetch data row by row, without loading the entire result set into memory. This is achieved through a mechanism that reads data from the database and presents it to your application as it becomes available. This is in contrast to techniques like `DataSet` or `DataTable`, which load all data upfront.

Key Advantages of DataReaders

Common DataReader Implementations

Depending on the specific data provider you are using, you will encounter different implementations of the DataReader interface:

While the concrete classes differ, they all implement the common IDataReader interface, providing a consistent way to interact with them.

Basic Usage Pattern

The typical pattern for using a DataReader involves the following steps:

  1. Establish a connection to the data source.
  2. Create a command object and associate it with the connection and a SQL query.
  3. Execute the command using ExecuteReader(), which returns a DataReader object.
  4. Iterate through the results using a while loop and the Read() method.
  5. Access column data by ordinal position or column name.
  6. Close the DataReader and the connection when finished.

Code Example (C# with SQL Server)

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

public class DataReaderExample
{
    public static void Main(string[] args)
    {
        string connectionString = "YourConnectionStringHere"; // Replace with your actual connection string
        string queryString = "SELECT ProductID, ProductName, UnitPrice FROM dbo.Products;";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            SqlCommand command = new SqlCommand(queryString, connection);

            try
            {
                connection.Open();
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    if (reader.HasRows)
                    {
                        while (reader.Read())
                        {
                            // Access data by ordinal position
                            int productId = reader.GetInt32(0);
                            string productName = reader.GetString(1);
                            decimal unitPrice = reader.GetDecimal(2);

                            Console.WriteLine($"ID: {productId}, Name: {productName}, Price: {unitPrice}");

                            // Alternatively, access data by column name
                            // int productIdByName = reader.GetInt32(reader.GetOrdinal("ProductID"));
                            // Console.WriteLine($"ID (by name): {productIdByName}");
                        }
                    }
                    else
                    {
                        Console.WriteLine("No rows found.");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }
    }
}

Accessing Data

You can access data from a DataReader in a few ways:

Important Considerations

When to Use DataReaders

DataReaders are ideal for scenarios such as: