Overview of the Data Provider Interfaces

Figure 13-2 shows a custom data provider's interfaces, grouped by function, and shows how they use each other. As you can see, the custom data provider has four objects: Connection, Command, Reader, and Adapter. The following sections discuss these objects and how they work.

click to expand
Figure 13-2: A custom data provider at a high level

Understanding the Connection Object

A Connection object is an individual session with a source of data. If it's a database connection, it's likely an open Transfer Control Protocol/Internet Protocol (TCP/IP) channel back to the server on a particular port that has been authenticated as having access to the database. If your data source is a file, it's likely a file handle on the file that will be read from. To fully understand how generic this interface is, take a look at the IDbConnection interface's properties in Table 13-1 and methods in Table 13-2.

Table 13-1: The Properties of the IDbConnection Interface




This property represents how the data provider can find its data source. In the case of a file-based source, this could be the path to the file. If it's a Web service, it could be a Uniform Resource Indicator (URI).


This property represents the amount of time the object should try to connect before giving up.


If connecting to a multiple data source such as an RDBMS, this is the name of the database to which it's connected. If connecting to an Extensible Markup Language (XML) file, it could potentially represent a section of the document.


This property represents the current state of the connection such as Open or Closed.

Table 13-2: The Methods of the IDbConnection Interface




Starts a transaction


Changes from one database to another within the current connection


Closes the connection


Returns an uninitialized instance of a command that works with this connection


Opens the connection

After reading through the methods and properties of this interface, it should be obvious that you can use the IDbConnection interface to manage a connection to virtually any type of resource imaginable.

Understanding the Command Object

The second major component of an ADO.NET data provider is the Command object as represented by the IDbCommand interface. This interface represents a single action taken on the data source.

The IDbCommand interface gets data from a data source or performs alterations on the data source. Everything else about the behavior of your Command object is up to you. This means that you can, if you want, define your own data query language (or your own dialect of SQL) that's optimized for dealing with the specific type of data with which your provider is dealing. However, developers who use SQL should probably write a SQL-like language. If you have a complete meta-language that requires interpretation, you can interpret the CommandText string to execute whatever commands you need on the data source. If, for example, you're creating a Command object around selecting and altering text files, you can use a regular expression and execute it against the text file and then return the results in a custom implementation of IDbDataReader. Table 13-3 describes the IDbCommand interface's properties, and Table 13-4 describes its methods.

Table 13-3: The Properties of the IDbCommand Interface




This property is a string that tells your Command object what to do. This can be SQL executed against the database, an XPATH query to choose a node in an XML document, or some other type of command that lets your command object know what it's expected to do.


This property represents the amount of time the command should wait before canceling its operation.


This property represents the type of command this is, such as a stored procedure or a text command.


This property represents the IDbConnection that this object uses.


This property represents a collection of IDbParameter objects. If your command requires any type of information from the calling program to know what to do, the Parameters collection is the place to do it.


This property represents the Transaction object that provides the context for a given transaction.


This property represents the row in the DataRow or DataTable that's being altered.

Table 13-4: The Methods of the IDbCommand Interface




Stops the current command


Creates a new parameter in the Parameters collection


Executes the command with no expectation for a result set to be returned


Returns an IDbDataReader object to iterate through the results of a query


Returns a single object from the execution of the command


Compiles or prepares the statement for execution if necessary

Understanding the Reader Object

The Reader object is a class that implements a number of interfaces; two interfaces are mandatory, and one interface is optional. The two required interfaces are IDataReader and IDataRecord, which provide the structure for iterating through any forward-only data collection. IDataReader allows for the iteration from one row to the next within your data source, and the IDataRecord object allows access to an individual row in the result set.

The optional interface to implement is the IEnumerable interface. If you choose to implement this interface, you can bind your IDataReader object directly to ASP.NET and Windows Forms controls. In practice, there really isn't any reason why you shouldn't implement this interface because you only have to implement one method that returns an instance of a DbEnumerator object.

As mentioned, to create a working data provider, you have to implement the IDataReader and IDataRecord interfaces. A little later in this chapter you'll see an example implementation of these methods coming together to provide a means of reading a pipe-delimited file. The DbEnumerator object already knows how to manipulate these interfaces and translate them into the behavior expected from a standard IEnumerable object. Think of implementing this interface as a no-pain, much-to-gain type of implementation. Listing 13-1 shows the implementation for an enumerator. Table 13-5 describes the IDataReader interface's properties, and Table 13-6 describes its methods.

Table 13-5: The Properties of the IDataReader Interface




The level of nesting in the result sets


Returns true if the connection is closed


Returns the number of records affected

Table 13-6: The Methods of the IDataReader Interface




Closes the result set


Returns a table with the schema of the result set


Advances to the next result


Reads a single record

Listing 13-1: The Implementation for an Enumerator

start example
 Public Function GetEnumerator() As IEnumerator Implements _ IEnumerable.GetEnumerator Return New System.Data.Common.DbEnumerator(Me) End Function 
end example

Using Visual Basic .NET, you'll find that creating the Reader object includes far more typing than actually thinking through the problem because of the level of verboseness required to implement an interface. Because the IDataRecord interface includes strongly typed methods to get a column's value, you have to create an implementation for each and every GetXXX method. Table 13-7 describes the IDataRecord interface's properties, and Table 13-8 describes its methods.

Table 13-7: The Properties of the IDataRecord Interface




The number of columns in the current row


A collection of objects that represents the current row

Table 13-8: The Methods of the IDataRecord Interface




Gets a Boolean value for the specified column


Gets a byte value for the specified column


Gets an array of bytes for the specified column


Gets a character for the specified column


Gets an array of characters for the specified column


Gets an IDataReader for the specified column, which is useful for nested structures of data


Gets a string that represents the data type for the specified column


Gets a DateTime object for the specified column


Gets a decimal for the specified column


Gets a double for the specified column


Gets a Type object for the specified column


Gets a Float object for the specified column


Gets a globally unique identifier for the specified column


Gets a 16-bit integer for the specified column


Gets a 32-bit integer for the specified column


Gets a 64-bit integer for the specified column


Gets a text name for the specified column


Gets the column number of the column of a specified name


Gets a string for the specified column


Gets an object for the specified column


Gets an array of objects for the specified column


Returns True if the current column is null

Understanding the Adapter Object

The Adapter object implements the IDbDataAdapter interface and inherits from the DbDataAdapter object. The purpose of this object is to glue together the four IDbCommand objects required to get and alter the database. It also defines how a DataSet should be filled and how to go about reflecting changes made in the DataSet back to your custom data source. Table 13-9 describes the properties of the IDbDataAdapter interface. Please note that this interface does not contain any methods, just properties.

Table 13-9: The Properties of the IDbDataAdapter Interface




The IDbCommand that loads data from the data source


The IDbCommand that inserts data into the data source


The IDbCommand that updates data in the data source


The IDbCommand that deletes data from the data source

The IDbDataAdapter interface simply defines the four IDbCommand objects and how they work with a DataSet. Depending on the requirements for your custom data provider, you can potentially set this in the constructor for your Adapter object. Table 13-10 describes the IDbDataAdapter interface's properties, and Table 13-11 describes its methods.

Table 13-10: The Properties of the IDbDataAdapter Object




Provides the name of the table that this adapter will use to manage its mappings


Determines if AcceptChanges is called on a DataRow when it's added to the DataSet


Gets a reference to the IContainer for this adapter (primarily used in the visual builder)


Determines if the rest of a DataSet is updated when there's an error on a single row


Determines what should be done if the adapter is unable to determine what action to execute


Determines what should be done if the DataSet's schema does not match the adapter's schema


Returns the ISite of this component, which is similar to a namespace but is for the Internet. This is similar to an XML namespace.


A collection of mappings between the source table and this DataTable

Table 13-11: The Methods of the IDbDataAdapter Object




Fills the DataSet using the SelectCommand of this adapter


Creates a DataTable within a DataSet with the schema handled by this adapter


Gets the parameters required for the SelectCommand to be properly called to fill up this data


Calls the appropriate InsertCommand, UpdateCommand, or DeleteCommand as required to update the data source to reflect the changes made in the DataSet


Fills in the values of the RowUpdatedEventArgs object with the proper values for this adapter


Fills in the values of a RowUpdatingEventArgs object with the proper values for this adapter


Creates an instance of the DataTableMappingCollection object


Creates a FillError event


Creates a RowUpdated event


Creates a RowUpdating event


If this object is serialized, determines whether the table mappings be serialized with it

As you can see, the DbDataAdapter object contains quite a few methods (Table 13-11 doesn't list all the methods, such as those inherited from MarshalByRefObject and Component). The good news is that you'll only have to override a few of them to create your custom data provider.


Most of the methods you implement can throw a NotSupportedException if that particular property or method doesn't have any context with your particular data source. You'll see this used in several places in the PipedDataProvider application in the next section of this chapter.

Applied ADO. NET(c) Building Data-Driven Solutions
Applied ADO.NET: Building Data-Driven Solutions
ISBN: 1590590732
EAN: 2147483647
Year: 2006
Pages: 214

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