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
- When you need to access data quickly without loading the entire result set.
- When you are processing large amounts of data row by row.
- When you only need to read the data and don't require updating capabilities.
The DataReader Workflow
The typical workflow for using a DataReader
involves the following steps:
- Create a
Command
object and set itsCommandText
andConnection
properties. - Execute the command using the
ExecuteReader()
method of theCommand
object. This returns aDataReader
object. - Open the connection to the data source.
- Use a loop (typically a
while
loop) with theRead()
method of theDataReader
to iterate through the rows. - Access column values within the loop using the
DataReader
's indexer (e.g.,reader[0]
orreader["ColumnName"]
) or specific methods likeGetString()
,GetInt32()
, etc. - 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.