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

PROPERTY

DESCRIPTION

ConnectionString

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).

ConnectionTimeout

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

Database

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.

State

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

Table 13-2: The Methods of the IDbConnection Interface

METHOD

DESCRIPTION

BeginTransaction()

Starts a transaction

ChangeDatabase()

Changes from one database to another within the current connection

Close()

Closes the connection

CreateCommand()

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

Open()

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

PROPERTY

DESCRIPTION

CommandText

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.

CommandTimeout

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

CommandType

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

Connection

This property represents the IDbConnection that this object uses.

Parameters

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.

Transaction

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

UpdatedRowSource

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

Table 13-4: The Methods of the IDbCommand Interface

METHOD

DESCRIPTION

Cancel()

Stops the current command

CreateParameter()

Creates a new parameter in the Parameters collection

ExecuteNonQuery()

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

ExecuteReader()

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

ExecuteScalar()

Returns a single object from the execution of the command

Prepare()

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

PROPERTY

DESCRIPTION

Depth

The level of nesting in the result sets

IsClosed

Returns true if the connection is closed

RecordsAffected

Returns the number of records affected

Table 13-6: The Methods of the IDataReader Interface

METHOD

DESCRIPTION

Close()

Closes the result set

GetSchemaTable()

Returns a table with the schema of the result set

NextResult()

Advances to the next result

Read()

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

PROPERTY

DESCRIPTION

FieldCount

The number of columns in the current row

Item

A collection of objects that represents the current row

Table 13-8: The Methods of the IDataRecord Interface

METHOD

DESCRIPTION

GetBoolean()

Gets a Boolean value for the specified column

GetByte()

Gets a byte value for the specified column

GetBytes()

Gets an array of bytes for the specified column

GetChar()

Gets a character for the specified column

GetChars()

Gets an array of characters for the specified column

GetData()

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

GetDataTypeName()

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

GetDateTime()

Gets a DateTime object for the specified column

GetDecimal()

Gets a decimal for the specified column

GetDouble()

Gets a double for the specified column

GetFieldType()

Gets a Type object for the specified column

GetFloat()

Gets a Float object for the specified column

GetGuid()

Gets a globally unique identifier for the specified column

GetInt16()

Gets a 16-bit integer for the specified column

GetInt32()

Gets a 32-bit integer for the specified column

GetInt64()

Gets a 64-bit integer for the specified column

GetName()

Gets a text name for the specified column

GetOrdinal()

Gets the column number of the column of a specified name

GetString()

Gets a string for the specified column

GetValue()

Gets an object for the specified column

GetValues()

Gets an array of objects for the specified column

IsDBNull()

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

PROPERTY

DESCRIPTION

SelectCommand

The IDbCommand that loads data from the data source

InsertCommand

The IDbCommand that inserts data into the data source

UpdateCommand

The IDbCommand that updates data in the data source

DeleteCommand

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

PROPERTY

DESCRIPTION

DefaultTableSourceName

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

AcceptChangesDuringFill

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

Container

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

ContinueUpdateOnError

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

MissingMappingAction

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

MissingSchemaAction

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

Site

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

TableMappings

A collection of mappings between the source table and this DataTable

Table 13-11: The Methods of the IDbDataAdapter Object

PROPERTY

DESCRIPTION

Fill()

Fills the DataSet using the SelectCommand of this adapter

FillSchema()

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

GetFillParameters()

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

Update()

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

CreateRowUpdatedEvent()

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

CreateRowUpdatingEvent()

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

CreateTableMappings()

Creates an instance of the DataTableMappingCollection object

OnFillError()

Creates a FillError event

OnRowUpdated()

Creates a RowUpdated event

OnRowUpdating()

Creates a RowUpdating event

ShouldSerializeTableMappings()

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.

Note

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