Commands and DataReaders

ADO.NET provides objects to interact with data sources. At the core of data manipulation are Command objects, used to execute SQL statements or stored procedures, and DataReader objects, used for efficient, forward-only, read-only access to data.

DbCommand Objects

The DbCommand class (and its provider-specific subclasses like SqlCommand for SQL Server or OracleCommand for Oracle) represents an SQL statement or stored procedure to be executed against a data source.

Key Properties:

Executing Commands:

Commands can be executed in various ways:

Example: Executing a SELECT query


using (SqlConnection connection = new SqlConnection(connectionString))
{
    string query = "SELECT CustomerID, CompanyName FROM Customers WHERE City = @City";
    SqlCommand command = new SqlCommand(query, connection);
    command.Parameters.AddWithValue("@City", "London");

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

    while (reader.Read())
    {
        Console.WriteLine($"ID: {reader["CustomerID"]}, Name: {reader["CompanyName"]}");
    }
    reader.Close();
}
            

DbDataReader Objects

DbDataReader (and its provider-specific subclasses like SqlDataReader) provides a way to retrieve a forward-only stream of rows from a data source. It is the most efficient way to retrieve data because it reads data as it is returned from the database, without buffering the entire result set in memory.

Key Methods:

Accessing Data:

Data can be accessed by column ordinal or column name. It's generally recommended to use the column ordinal for performance, obtained using GetOrdinal.


int idOrdinal = reader.GetOrdinal("CustomerID");
int nameOrdinal = reader.GetOrdinal("CompanyName");

while (reader.Read())
{
    if (!reader.IsDBNull(idOrdinal))
    {
        int customerId = reader.GetInt32(idOrdinal);
        string companyName = reader.GetString(nameOrdinal);
        Console.WriteLine($"ID: {customerId}, Name: {companyName}");
    }
}
            
Performance Tip: For maximum performance when reading data, use GetOrdinal to retrieve column ordinals once outside the loop and then use these ordinals to access column values. This avoids repeated string lookups within the loop.
Important: Always call Close() on the DataReader when you are finished with it, or use a using statement to ensure it is properly disposed of and the connection is released.