Provider Architecture

for RuBoard

As mentioned on Day 1, "ADO.NET In Perspective," a provider's main responsibilities include connecting and disconnecting with a data store, performing transaction management, handling exceptions, executing parameterized queries and commands, and then either processing the results directly or interacting with the DataSet object. To that end, ADO.NET provides classes and interfaces in the System.Data and System.Data.Common namespaces that are used as a template for developers building providers to work with specific data stores.

Note

As you look at these common interfaces, you might be wondering why, for the most part, the interfaces such as IDataReader are in the System.Data namespace, but the classes such as DbDataAdapter are in System.Data.Common . The reason is that the classes in System.Data.Common are meant to be used only by developers implementing providers, whereas the interfaces are used both by developers of providers and users wanting to write polymorphic code against multiple providers.


graphics/newterm.gif

As you're well aware by now, Microsoft ships the SQL Server provider in the System.Data.SqlClient namespace (referred to simply as SqlClient) and the OLE DB provider in the System.Data.OleDb namespace (referred to as OleDb). In addition, the ODBC provider is available as a download from the MSDN Web site. The SqlClient provider is an example of a specific provider (sometimes referred to as a native or targeted provider ) that communicates with a single data store (SQL Server 7.0 or later) and exposes functionality particular to that data store. Both the OleDb are ODBC providers are examples of generic providers (sometimes referred to as bridge or broad providers ) that act as a managed interface to data that is accessed through an OLE DB provider or ODBC driver, respectively. As such, these generic providers don't offer any functionality not already exposed by the OLE DB provider or ODBC driver. Obviously, specific providers offer not only the opportunity for exposing functionality available to the data store, such as returning XML directly from SQL Server, but also offer performance improvements because the extra layer of abstraction is eliminated. For example, SqlClient talks to SQL Server directly using the Tabular Data Stream (TDS) protocol.

Note

Microsoft is also working on additional providers. For example, beta 1 of the Oracle .NET Data Provider was released on MSDN in early May of 2002, and it is rumored that a DB2 provider is not far behind.


The provision of the classes and interfaces for building providers not only promotes a common programming model but also actually allows you to write code polymorphically to mask the provider being used. (We'll discuss one technique for doing so on Day 17, "ADO.NET in the Data Services Tier .") In addition to implementing the standard classes and interfaces, providers typically implement additional classes that provide error handling and other services, as shown in Figure 8.1 and explained in Table 8.1.

Figure 8.1. Provider architecture. This diagram highlights the objects typically exposed by a provider. The highlighted objects have classes or interfaces provided by ADO.NET.

graphics/08fig01.gif

Note

As I'll mention on Day 21, "Futures and Wrap-Up," look for features in future releases of ADO.NET that make it easier to write provider- independent code.


Table 8.1. Provider components. This table details each of the primary components of a provider and what each is used for.
Component Description
Data Adapter Implemented using the IDbDataAdapter or IDataAdapter interfaces of the System.Data namespace and/or the DbDataAdapter and DataAdapter classes of the System.Data.Common namespace. The data adapter is used to populate a DataSet from a connection to a data store and synchronize changes made to the DataSet with the data store.
Connection Implemented using the IDbConnection interface of the System.Data namespace and used as the means to send queries and commands to the data store. Connection objects control the transactional behavior of the data store and typically raise events and exceptions when the connection state changes or when errors are encountered .
Transaction Implemented using the IDbTransaction interface of the System.Data namespace. Associated with a connection object and used to initiate, commit, and roll back logical units of works in the data store.
Permissions Implemented using the DbDataPermission and DbDataPermissionAttribute classes of the System.Data.Common namespace. These classes are used with the code access security system in .NET and, in fact, are derived from classes in the System.Security namespace. They are used to ensure that a user has a security level adequate to access data through the provider. Providers derive classes from these so that both imperative and declarative security checks can be specified directly in the code and made by the runtime when the code is loaded or executed.
Command Builder Not implemented by all providers; as a result, there is no corresponding class or interface for developers to use. The primary purpose is to automatically build the insert, update, and delete commands used by the data adapter to populate and synchronize data between a DataSet and a data store.
Command Implemented using the IDbCommand interface of the System.Data namespace and used to encapsulate a command, typically some variant of SQL, that may be executed through a connection object. Commands may be associated with one or more parameters passed to the data store. For relational data stores, commands can typically be either dynamic (containing SQL SELECT , INSERT , UPDATE , and DELETE statements) or refer to procedures or packages stored on the server.
Data Reader Implemented using the IDataReader and IDataRecord interfaces of the System.Data namespace and used to stream through data returned from a command object in a forward-only, read-only manner. Data readers expose the second major programming model in ADO.NET using a streamed and connected approach as opposed to a cached and disconnected approach exposed through the DataSet .
Parameter Implemented using the IDataParameter , IDbDataParameter , and IDataParameterCollection interfaces of the System.Data namespace. The first two interfaces listed are used to implement actual parameter classes that map to a name -value pair of a specific data type passed to a command object. The third interface is used to create classes that hold collections of parameters that can be associated with a command object.
Error Not implemented by all providers; as a result, there are no classes or interfaces in the System.Data namespace to use as templates. Providers implement custom error classes to expose individual errors generated by the data store. In that way, errors can be exposed with properties consistent for the data store. Providers also implement classes used to hold a collection of errors so that if the data store throws more than one error they can all be encapsulated in a single object.
Exception Not implemented by all providers and so ADO.NET does not contain a generic Exception class. Providers derive their own exception from System.Exception and use it to point to the collection of errors generated by the data store. By using a custom exception class, clients can more easily construct structured exception handling blocks to deal with errors generated by the provider.

For the remainder of today, you'll walk through each of the items in Table 8.1 and explore it in more detail.

Note

The items shown in Table 8.1 and Figure 8.1 are the primary classes and interfaces. Of course, supplementary classes and interfaces are used within each of the primary items shown here.


As a final note, as mentioned on Day 1, the idea of having different providers to access different data stores at the programmatic level is a departure from the architecture used by Microsoft in DAO, RDO, and ADO. In all those programming models, the idea was that code specific to the data store was abstracted at a lower level into the OLE DB provider or ODBC provider so that the code written by developers differed only slightly, even when accessing different data stores. These small differences included things such as connection strings, the variant of SQL used, and the names of objects such as stored procedures.

Although relying on common interfaces provided by ADO.NET goes some way toward allowing provider-independent code to be written, ADO.NET does not provide the uniform programming model of ADO. This is intentional. The reason is that the cost of building a programming model like ADO ”where the Recordset object provided both streamed, batch, and immediate access to the underlying data ”is confusion on the part of developers, which results in inefficient code. A good deal of the confusion is related to the fact that OLE DB providers and ODBC drivers don't expose the same set of functionality, so ADO would reset properties based on the functionality available. A typical example is when the ADO developer wants to use a dynamic cursor in order to see changes to the database as they occur, only to find out that the CursorType property of the Recordset object was reset from adOpenDynamic to adOpenStatic , resulting in all the records being downloaded to the client or middle tier, thereby expending extra resources.

for RuBoard


Sams Teach Yourself Ado. Net in 21 Days
Sams Teach Yourself ADO.NET in 21 Days
ISBN: 0672323869
EAN: 2147483647
Year: 2002
Pages: 158
Authors: Dan Fox

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net