The DataAdapter
object is a key component in ADO.NET, acting as a bridge between a Dataset
and a data source. Its primary role is to retrieve data from the data source and populate a Dataset
, and then to reconcile changes made in the Dataset
back to the data source.
Core Functionality
DataAdapter
objects abstract the underlying data provider. For example, SqlDataAdapter
works with SQL Server, while OdbcDataAdapter
works with ODBC-compliant data sources.
The main operations performed by a DataAdapter
are:
- Fill: Populates a
Dataset
with data from a data source. - Update: Propagates changes made to a
Dataset
back to the data source. - SelectCommand: Retrieves data.
- InsertCommand: Inserts new rows.
- UpdateCommand: Updates existing rows.
- DeleteCommand: Deletes rows.
Key Classes
The ADO.NET data providers implement concrete classes for DataAdapter
. The most common ones include:
System.Data.SqlClient.SqlDataAdapter
for SQL Server.System.Data.OleDb.OleDbDataAdapter
for OLE DB providers.System.Data.Odbc.OdbcDataAdapter
for ODBC data sources.System.Data.OracleClient.OracleDataAdapter
for Oracle databases.
Using DataAdapter
The typical workflow involves:
- Creating a
Connection
object to your data source. - Creating a
Command
object to execute a query or stored procedure. - Creating a
DataAdapter
object, passing theCommand
andConnection
to its constructor or setting their properties. - Creating a
Dataset
object. - Calling the
Fill()
method of theDataAdapter
, passing theDataset
and the name of the table to populate. - After making modifications to the
Dataset
, calling theUpdate()
method of theDataAdapter
, passing theDataset
.
Example: Filling a Dataset
using System;
using System.Data;
using System.Data.SqlClient;
// ...
using (SqlConnection connection = new SqlConnection("YourConnectionString"))
{
SqlDataAdapter adapter = new SqlDataAdapter("SELECT * FROM Customers", connection);
DataSet dataSet = new DataSet();
connection.Open();
adapter.Fill(dataSet, "Customers");
connection.Close();
// Now you can work with the data in dataSet.Tables["Customers"]
foreach (DataRow row in dataSet.Tables["Customers"].Rows)
{
Console.WriteLine(row["CustomerID"] + " - " + row["CompanyName"]);
}
}
Example: Updating a Dataset
using System;
using System.Data;
using System.Data.SqlClient;
// ... Assuming dataSet is already populated and modified
using (SqlConnection connection = new SqlConnection("YourConnectionString"))
{
SqlDataAdapter adapter = new SqlDataAdapter("SELECT CustomerID, CompanyName FROM Customers", connection);
// Configure the UpdateCommand for the Customers table
adapter.UpdateCommand = new SqlCommand("UPDATE Customers SET CompanyName = @CompanyName WHERE CustomerID = @CustomerID", connection);
adapter.UpdateCommand.Parameters.Add("@CompanyName", SqlDbType.VarChar, 50, "CompanyName");
adapter.UpdateCommand.Parameters.Add("@CustomerID", SqlDbType.Int, 0, "CustomerID");
connection.Open();
int rowsAffected = adapter.Update(dataSet, "Customers");
connection.Close();
Console.WriteLine($"{rowsAffected} rows updated.");
}
Handling Updates
The Update()
method uses the InsertCommand
, UpdateCommand
, and DeleteCommand
properties to apply changes. If these commands are not set, the Update()
method will throw an exception. The DataAdapter
automatically detects the state of each row (Added, Modified, Deleted) and executes the appropriate command.
Note: When using UpdateCommand
, InsertCommand
, or DeleteCommand
, you must define the parameters correctly, mapping them to the columns in your Dataset
using the SourceColumn
property.
DataAdapter Events
DataAdapter
objects expose several events that allow you to intervene in the data retrieval and update process:
RowUpdating
: Fired before a row is updated.RowUpdated
: Fired after a row has been updated.FillUpdating
: Fired before the entire fill operation.FillUpdated
: Fired after the entire fill operation.
Advantages of DataAdapter
- Abstraction: Hides the complexities of the data provider.
- Efficiency: Optimized for batch operations.
- Flexibility: Works seamlessly with
Dataset
objects for disconnected data scenarios.
Tip: For simple data retrieval where updates are not required, a DataReader
is often more efficient as it provides a forward-only, read-only stream of data.