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
DataTableobjects. - Relations: A collection of
DataRelationobjects 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 aDataSetwith data from the data source.SelectCommand: TheCommandobject used to retrieve data.InsertCommand: TheCommandobject used to insert new records.UpdateCommand: TheCommandobject used to update existing records.DeleteCommand: TheCommandobject 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
DataAdapterexamines theRowStateof 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
RowStateof 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.