Team LiB
Previous Section Next Section

Custom Data Providers

A custom data provider, in the context of ADO.NET and the .NET Framework, is a suite of classes that provide programmatic access to some data source using a set of consistent interfaces. The data source can be anything you like. There are custom providers for flat-file databases that have no corresponding ODBC driver, providers for Reflection, and even a provider for MSMQ (Microsoft Message Queuing) data communication.

The point is that, whatever the data source, the interface and API to gain access to that data is consistent between your provider, Microsoft's providers, and any other implemented providers. The next section gives you guidelines to determine when you should create a custom provider, how you should create one, and why you should do so, using a hypothetical scenario as an example.

When to Create a Data Provider

There are plenty of reasons to create a data provider. The first and foremost reason is that your data cannot be accessed via one of the standard access methods:

  • SQL Server (managed ADO.NET provider)

  • OLE DB (managed ADO.NET provider)

  • ODBC (managed ADO.NET provider)

  • XML (standard .NET XML classes)

If your data cannot be accessed by any of the preceding means, you should definitely consider creating your own provider to give consumers of your data a familiar, fast, and consistent interface.

Another situation in which you might need to create your own data provider is when an ADO.NET provider can access your data, but its access isn't native. Creating your own managed provider might give programmers faster and more powerful functionality as well as access to more features of your particular data source.

If your data source doesn't make use of things such as connections or transactions, and it is pure data, creating your own provider might be overkill. It might be more work than is necessary and you could be able to accomplish what you need by exposing your data as XML instead of through a custom provider.

Also, if your data source is a fully functional RDBMS that has all the features associated with common database servers such as SQL and Oracle, you might want to consider writing an OLE DB provider and using the .NET managed OLE DB provider to access it. If you think you can create faster access by writing your own provider and bypassing OLE DB, doing so might be your best bet.

Steps for Implementing a Custom Data Provider

Even though it might look like a lot of work, implementing a custom ADO.NET data provider is a very straightforward process. The .NET Framework provides a series of interfaces that you can implement. By creating a library that contains class implementations for those classes, you can create your own custom data provider. You can choose to implement as many or as few of the data provider interfaces as you like, provided you can still provide the appropriate functionality. The interfaces that can be implemented in a custom provider library are as follows:

  • IDataParameter

  • IDataParameterCollection

  • IDbConnection

  • IDbCommand

  • IDbDataReader

  • IDbDataAdapter

As the chapter steps through the process of building a custom provider, you will see each of these interfaces, their intended functionality, and a custom implementation of each interface. Before getting to the code, take a look at the sample scenario for which a data provider will be built.

Sample Data Provider Scenario

As mentioned earlier, you should not create a data provider if your data can be accessed via one of the standard data providers that ships with the .NET Framework or if your data can be exposed and accessed via XML.

The example discussed throughout this chapter creates a custom data provider to solve a unique problem. A fictitious company has decided that it needs to have its applications access data remotely. For some reason (IT security, firewalls, and so on), the ports normally used to transmit SQL data are not available to the client. Also, for various business reasons, the company has decided that the business logic must reside on the client side. Finally, the company must be able to write the client code in such a way that if the data were to become local (instead of remote behind a firewall), the application could be quickly modified to work in that way.

What the client programmers need is an ADO.NET provider that they can use generically via interfaces that will give them firewall-friendly access to a data tier on the other side. For this solution, you are going to create a data provider that works just like any other data provider, but instead of connecting to a database, it will connect to a web service that will blindly forward queries to a secure back-end.

The architecture shown in Figure 28.1 provides a good illustration of the network topology in which this provider will exist.

Figure 28.1. Architecture of the sample data provider.

Overview of the Remote Data Provider

The sample architecture you saw in Figure 28.1 provides a good high-level overview of what you're trying to accomplish. On a lower level, the main concept is changing the concept of a connection within the ADO.NET data provider paradigm from a database connection to a web service connection.

When commands are executed against this new custom provider, they will be serialized and then sent to the web service. The data will be returned from the web service, and the data provider clients can do whatever they want with the results, such as open a DataReader or fill a DataSet, and so forth. Not all the methods that are part of the provider have been implemented, so you will notice that things such as Fill() on a DataSet are not supported. After you've completed this chapter, it might be a useful exercise to modify this provider to give additional functionality and to support the DataAdapter's Fill operation and so on.

The following code is a sample of the code that will be used to access the custom provider:

RDPConnection conn =
  new RDPConnection("http://localhost/DataService/DataHost.asmx");
RDPCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Customers";
cmd.CommandType = CommandType.Text;
RDPDataReader reader = cmd.ExecuteReader( CommandBehavior.Default );
while (reader.Read())
    reader.GetString(0), reader.GetString(1), reader.GetString(2));

Because this particular provider simply forwards requests to a web service, the client application need not store things such as the SQL Server connection string, passwords, IP addresses for database servers, and so on. All it needs is the URL to the database back-end web service. Figure 28.2 shows the console output of the preceding program (you might recognize the data from the Northwind database).

Figure 28.2. The sample remote data provider consumer application in action.

    Team LiB
    Previous Section Next Section