DataAdapters and DataSets
DataSets and DataAdapters are fundamental components of ADO.NET that facilitate disconnected data access. A DataSet
represents a set of data in memory, independent of any data source, while a DataAdapter
acts as a bridge, filling a DataSet
with data from a data source and resolving changes to that data back to the data source.
The DataSet Object
The DataSet
is an in-memory representation of data. It can contain multiple, related DataTable
objects, each representing a table of data. These tables can be linked via DataRelation
objects, mirroring the relationships in a relational database.
- Tables: A collection of
DataTable
objects. - Relations: A collection of
DataRelation
objects defining how tables are related. - Constraints: Rules like primary keys and unique constraints applied to tables.
DataSet
is designed for disconnected scenarios, allowing you to retrieve data, modify it, and then submit those changes back to the source.
The DataAdapter Object
The DataAdapter
is the primary mechanism for moving data between a DataSet
and a data source. Different providers (e.g., SQL Server, Oracle, OleDb) offer specific DataAdapter
implementations (like SqlDataAdapter
, OracleDataAdapter
, OleDbDataAdapter
).
A DataAdapter
typically has four core operations:
Fill()
: Populates aDataSet
with data from the data source.SelectCommand
: TheCommand
object used to retrieve data.InsertCommand
: TheCommand
object used to insert new records.UpdateCommand
: TheCommand
object used to update existing records.DeleteCommand
: TheCommand
object used to delete records.
The DataAdapter
manages the process of sending commands to the data source and processing the results. It uses Connection
objects internally to communicate with the database.
Working with DataAdapters and DataSets
Here's a simplified example of how to use a SqlDataAdapter
and a DataSet
to retrieve data:
using System;
using System.Data;
using System.Data.SqlClient;
public class DataAccess
{
public static void RetrieveData(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
string sql = "SELECT CustomerID, CompanyName, ContactName FROM Customers";
SqlDataAdapter adapter = new SqlDataAdapter(sql, connection);
DataSet dataSet = new DataSet();
try
{
connection.Open();
adapter.Fill(dataSet, "Customers"); // Fills the DataSet with data from the "Customers" table
// Now you can work with the data in the DataSet
DataTable customersTable = dataSet.Tables["Customers"];
foreach (DataRow row in customersTable.Rows)
{
Console.WriteLine($"ID: {row["CustomerID"]}, Company: {row["CompanyName"]}, Contact: {row["ContactName"]}");
}
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
}
}
Updating Data
Updating data involves modifying the rows in the DataSet
and then calling the DataAdapter.Update()
method. The DataAdapter
automatically determines which rows have been added, modified, or deleted and executes the appropriate INSERT
, UPDATE
, or DELETE
commands.
DataAdapter.Update()
Process:
- The
DataAdapter
examines theRowState
of each row in the specifiedDataTable
. - For added rows (
RowState.Added
), it executes theInsertCommand
. - For modified rows (
RowState.Modified
), it executes theUpdateCommand
. - For deleted rows (
RowState.Deleted
), it executes theDeleteCommand
. - After a successful update, the
RowState
of the affected rows is reset toUnchanged
.
AcceptChangesDuringUpdate
property of the DataAdapter
.
Benefits of Disconnected Data Access
- Scalability: Applications can retrieve data, close the connection, perform operations, and then re-open the connection to submit changes, reducing the time database connections are held open.
- Performance: Reduces network traffic and database load by fetching data in batches.
- Flexibility: Allows for complex data manipulation and business logic to be applied to the data in memory without constant database interaction.