MSDN Documentation

Microsoft Developer Network

Error Handling in ADO.NET

Effective error handling is crucial for robust application development. ADO.NET provides mechanisms to catch and manage exceptions that occur during data access operations.

Understanding Exceptions

When an error occurs during an ADO.NET operation, the .NET Framework throws an exception. The most common base class for exceptions is `System.Exception`. ADO.NET operations typically throw exceptions derived from `System.Data.DataException` or specific provider exceptions.

Common Exception Types in ADO.NET:

Implementing Try-Catch Blocks

The standard C# mechanism for handling exceptions is the `try-catch` block. This allows you to enclose code that might throw an exception and define how to respond if one occurs.

Example: Handling a `SqlException`

using System.Data.SqlClient;

public class DataAccess
{
    public void ExecuteQuery(string connectionString, string query)
    {
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            using (SqlCommand command = new SqlCommand(query, connection))
            {
                try
                {
                    connection.Open();
                    command.ExecuteNonQuery();
                    Console.WriteLine("Query executed successfully.");
                }
                catch (SqlException ex)
                {
                    Console.WriteLine("SQL Error encountered:");
                    foreach (SqlError error in ex.Errors)
                    {
                        Console.WriteLine($"  Number: {error.Number}, Message: {error.Message}, Procedure: {error.Procedure}, Server: {error.ServerName}, Line: {error.LineNumber}");
                    }
                    // Log the error or take other appropriate action
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"An unexpected error occurred: {ex.Message}");
                    // Log the error
                }
                finally
                {
                    // Resources are automatically disposed by 'using' statements
                    Console.WriteLine("Operation finished.");
                }
            }
        }
    }
}

The `Errors` Collection

SQL Server `SqlException` objects contain an `Errors` collection. This collection provides detailed information about each error returned by SQL Server. Iterating through this collection can give you a more granular view of what went wrong.

Handling Multiple Errors

Some operations, particularly batch SQL statements, can result in multiple errors. The `Errors` collection is designed to capture all such errors.

Tip:

Always include a generic `catch (Exception ex)` block as a fallback to capture any unexpected errors that might not be specific to data access.

Data `RowError` Property

Within a `DataTable`, each `DataRow` has a `RowError` property. This property can be used to store a custom error message associated with that specific row. This is useful when validating data before committing changes.

Example: Setting `RowError`

public void ValidateRow(DataRow row)
{
    if (string.IsNullOrEmpty(row["ProductName"].ToString()))
    {
        row.RowError = "Product Name cannot be empty.";
    }
    else
    {
        row.RowError = string.Empty; // Clear any previous error
    }
}

Best Practices for Error Handling

By implementing these error handling strategies, you can create more reliable and user-friendly applications that interact with data sources.