Understanding how ADO.NET handles data values is fundamental to effective data access. ADO.NET provides robust mechanisms for representing, manipulating, and converting various data types that originate from diverse data sources.

Data Types and .NET Types

ADO.NET maps database-specific data types to corresponding .NET Framework data types. This mapping ensures type safety and allows you to work with data using familiar .NET objects. For example, a SQL Server INT is typically mapped to a .NET System.Int32.

Common Mappings

Database Type .NET Type
VARCHAR, NVARCHAR, TEXT System.String
INT, INTEGER System.Int32
BIGINT System.Int64
FLOAT, DOUBLE PRECISION System.Double
DECIMAL, NUMERIC System.Decimal
BIT System.Boolean
DATE, DATETIME, TIMESTAMP System.DateTime
BINARY, VARBINARY, BLOB System.Byte[]

Handling Null Values

Database systems commonly use NULL to represent missing or unknown data. In ADO.NET, null values are typically represented by their corresponding .NET type's default value (e.g., 0 for numeric types, an empty string for string types) or, more explicitly, by using the DBNull.Value object.

It's crucial to check for null values before attempting to use them to avoid exceptions. The IsNull method of the DataRow object or checking if the value equals DBNull.Value are common approaches.

Checking for Null Values


// Assuming 'row' is a DataRow and 'columnName' is the name of a column
if (row[columnName] != DBNull.Value)
{
    // Process the non-null value
    string value = row[columnName].ToString();
    Console.WriteLine($"Value: {value}");
}
else
{
    // Handle the null value
    Console.WriteLine("Value is null.");
}
            

DBNull.Value

System.DBNull.Value is a singleton object that represents a missing value from a data source. It's important to distinguish between a .NET type's default value and a database NULL. For instance, an empty string ("") is not the same as a database NULL for a string column.

Always use DBNull.Value to represent and check for database NULLs when interacting with data providers.

Type Conversions

ADO.NET provides powerful methods for converting data types. The Convert class in System, along with specific methods on `System.Object` (like ToString()), and data-type specific conversion methods (e.g., Convert.ToInt32()) are commonly used.

Type Conversion with Convert Class

The System.Convert class offers a wide range of methods to convert between various .NET data types. When dealing with data retrieved from a database, you'll often use these methods to cast or convert the underlying values.

Converting to Integer


object dataValue = row["Age"]; // Assume this could be an INT or null
int age = 0;

if (dataValue != DBNull.Value)
{
    try
    {
        age = Convert.ToInt32(dataValue);
        Console.WriteLine($"Age: {age}");
    }
    catch (FormatException)
    {
        Console.WriteLine("Invalid format for Age.");
    }
    catch (OverflowException)
    {
        Console.WriteLine("Age value out of range for Int32.");
    }
}
else
{
    Console.WriteLine("Age is not available.");
}
            

Nullable Types

C# 2.0 and later introduced nullable value types (e.g., int?, bool?, DateTime?). These are invaluable when working with ADO.NET data, as they elegantly handle the distinction between a value and a null. A nullable type can hold either its underlying value type or null.

Using Nullable Types


// Assuming 'row' is a DataRow and 'NullableColumn' is a column that can be null
int? nullableValue = null;

if (row["NullableColumn"] != DBNull.Value)
{
    nullableValue = Convert.ToInt32(row["NullableColumn"]);
}

if (nullableValue.HasValue)
{
    Console.WriteLine($"Nullable value: {nullableValue.Value}");
}
else
{
    Console.WriteLine("Nullable value is DBNull.");
}
            

Working with Specific Data Types

Beyond the common types, ADO.NET provides support for more specialized data types like System.DateTimeOffset, System.TimeSpan, and binary large objects (BLOBs).

Binary Data (BLOBs)

For large binary data, ADO.NET uses System.Byte[]. When retrieving BLOBs, you can read them into a byte array. For very large BLOBs, consider streaming mechanisms to avoid loading the entire data into memory.

When dealing with potentially large data, always consider performance implications. Avoid unnecessary data conversions and always check for nulls.

By mastering the representation and manipulation of data values in ADO.NET, you can build more robust, efficient, and error-free data-driven applications.