Design of the Data Access Application Block
The Data Access Application Block includes the following features:
- A simple and efficient way of working with different database systems (see Designing for Simplified Data Access)
- A way of developing database-agnostic applications (see Designing for Database-Agnostic Applications)
- An easy way to adjust and validate the database configuration settings
Design Goals
The application block was designed to achieve the following goals:
- Encapsulate the logic used to perform the most common data access tasks.
- Eliminate common coding errors, such as failing to close connections.
- Relieve developers of the need to write duplicated code for common data access tasks.
- Reduce the need for custom code.
- Incorporate good practices for data access.
- Ensure that, as far as possible, the application block functions work with different types of databases.
- Ensure that applications written for one type of database are, in terms of data access, the same as applications written for another type of database.
Design Highlights
The following schematic illustrates the interrelationship between the key classes in the Data Access Application Block, excluding those specifically designed to support asynchronous operations and data accessors.
The block class uses configuration information found in the configuration file to determine the specific Database object type to construct and return to the application when code requests an instance of the Database class. It uses the following criteria to determine the Database object type to construct:
If the client code passes a database instance name that identifies a connection string in the configuration file, it uses that string to create the Database object.
Note
The .NET Framework classes maintain the connection strings in the connectionStrings section of the configuration file. This means that connection string definitions can be shared among all applications that access the connectionStrings section.
If the client code does not pass a database instance name, the block identifies the connection string by the default instance setting in the configuration file. The defaultDatabase attribute in the dataConfiguration configuration section controls the default instance. The following XML fragment from a configuration file shows a default instance that corresponds to the Production connection string.
<dataConfiguration defaultDatabase="Production">
The <connectionStrings> section in the configuration file maps logical identifiers (names) to connection strings and DbProviderFactory types. The block obtains the logical name of the ADO.NET data provider from the connection string and then calls the .NET Framework DbProviderFactory class to obtain the fully qualified type name for the ADO.NET data provider. It uses this information to determine the type of Database object to construct. Although the .NET Framework considers database provider names in connection strings to be optional, the Data Access Application Block requires them.
The application block configuration code contains default mappings. These map a SqlDatabase object to a System.Data.SqlClient data provider, an OracleDatabase object to a System.Data.OracleClient data provider, and a GenericDatabase object to all other data providers. You can use the configuration tools to override the default mappings.
Changing the default mappings or using the configuration tools to add new mappings creates a providerMappings section in the configuration file. The providerMappings section maps the DbProviderFactory type to the Database type. You can add your own mapping by creating your own database class and mapping it to a DbProviderFactory object.
The abstract base class Database defines the common interface and provides much of the implementation for the data access methods. The SqlDatabase class and OracleDatabase class derive from the Database class. They provide methods to their respective database server systems, which include common functionality that is implemented differently from database to database, as well as functionality unique to that database system. The application block also includes a GenericDatabase class. This class does not provide any database-specific features but operates with any ADO.NET data provider.
The application block supports the dynamic discovery of parameters for stored procedures. This discovery requires a round trip to the database system. The ParameterCache class allows parameter information to be cached, thus avoiding round trips for subsequent invocations of the same stored procedure. (The GenericDatabase class does not support parameter discovery).