Reading Data with DataReader

The DataReader object provides a forward-only, read-only stream of data from a data source. It is an efficient way to retrieve a result set when you need to process rows as they are read, rather than loading the entire result set into memory.

When to Use DataReader

The DataReader Workflow

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

  1. Create a Command object and set its CommandText and Connection properties.
  2. Execute the command using the ExecuteReader() method of the Command object. This returns a DataReader object.
  3. Open the connection to the data source.
  4. Use a loop (typically a while loop) with the Read() method of the DataReader to iterate through the rows.
  5. Access column values within the loop using the DataReader's indexer (e.g., reader[0] or reader["ColumnName"]) or specific methods like GetString(), GetInt32(), etc.
  6. Close the DataReader when you are finished with it. This also releases the connection.

Example: Reading Data with SqlDataReader

Here's a C# example demonstrating how to read data using SqlDataReader:

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

public class DataReaderExample
{
    public static void Main(string[] args)
    {
        string connectionString = "Your_Connection_String_Here";
        string queryString = "SELECT ProductID, ProductName, UnitPrice FROM dbo.Products;";

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

            try
            {
                connection.Open();
                SqlDataReader reader = command.ExecuteReader();

                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        // Access data by column ordinal or name
                        int productId = reader.GetInt32(0); // Using ordinal index
                        string productName = reader.GetString(1); // Using ordinal index
                        decimal unitPrice = reader.GetDecimal(reader.GetOrdinal("UnitPrice")); // Using GetOrdinal

                        Console.WriteLine($"ID: {productId}, Name: {productName}, Price: {unitPrice:C}");
                    }
                }
                else
                {
                    Console.WriteLine("No rows found.");
                }
                reader.Close(); // Ensure the reader is closed
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
            // The 'using' statement ensures the connection is closed automatically.
        }
    }
}
                
            

Key DataReader Properties and Methods

Member Description
Read() Advances the DataReader to the next record in the result set. Returns true if there are more rows; otherwise, false.
HasRows Gets a value indicating whether the DataReader contains one or more rows.
FieldCount Gets the number of columns in the current row.
IsDBNull(ordinal) Returns true if the specified column contains a null value.
GetOrdinal(columnName) Returns the zero-based column ordinal of the specified column name.
GetString(ordinal), GetInt32(ordinal), GetDecimal(ordinal), etc. Retrieves the value of the specified column as the specified data type.
Item[ordinal] or Item[columnName] Gets the value of the specified column as an Object.
Close() Closes the DataReader object.

Important Note on Connections

When using a DataReader, the associated database connection is typically held open until the DataReader is closed. Ensure you close the DataReader promptly after use, or utilize a using statement to guarantee closure.

Performance Tip

For optimal performance, retrieve only the columns you need by specifying them in your SQL query rather than using SELECT *. Also, use the specific type-retrieval methods (e.g., GetInt32) when you know the data type to avoid unnecessary type conversions.