Search
« Proxy Data Provider with WCF – Service | Main | Proxy Data Provider with WCF - Architecture »
Sunday
Jul262009

Proxy Data Provider with WCF – Contract

This article is a continuation of a longer tutorial. If you haven’t done so already you should read it from the beginning.

Contract

The contract defines which operations the WCF Service provides. This is also the only assembly that both the client and server will have in common.

The WCF Data Provider is just a proxy on top of other data providers. This means that most of the methods will be close to a 1:1 mapping of the methods and properties in the ADO.Net data provider interfaces (IDbConnection, IDbCommand, etc).

There are a few things we need to take special note of in the contract.

   10 [ServiceContract]

   11 public interface IWcfDataProvider

   12 {

   13     #region IDbConnection

   14     [OperationContract]

   15     string CreateConnection(string invariantName);

   16 

   17     [OperationContract]

   18     void SetConnectionString(string token, string connectionString);

   19 

   20     [OperationContract]

   21     string GetConnectionString(string token);

   22 

   23     [OperationContract]

   24     void ChangeDatabase(string token, string databaseName);

   25 

   26     [OperationContract]

   27     void Close(string token);

   28 

   29     [OperationContract]

   30     int GetConnectionTimeout(string token);

   31 

   32     [OperationContract]

   33     string CreateCommand(string token);

   34 

   35     [OperationContract]

   36     string GetDatabase(string token);

   37 

   38     [OperationContract]

   39     void Open(string token);

   40 

   41     [OperationContract]

   42     System.Data.ConnectionState GetState(string token);

   43 

   44     [OperationContract]

   45     void DisposeConnection(string token);

   46     #endregion

   47 

 

   82     [OperationContract]

   83     string ExecuteReaderWithBehavior(string token, CommandBehavior behavior);

   84 

   85     [OperationContract]

   86     string ExecuteReader(string token);

  1. CreateConnection takes a string invariantName and returns a string.
    1. The WCF Service can be used to connect to any data provider installed on the host machine. To know what type to connect to the client must provide the Invariant Name for that provider. This gets passed unmodified to the DbProviderFactories to construct the relevant class factory.
    2. Returns a token to represent this connection instance.
  2. Virtually all methods have a token parameter. Because the WCF Service can be used by multiple clients to create multiple connections at a time, the service needs to know which connection to operate against. When the client requests a new object (DbConnection, DbCommand, etc) to be created the service will store it and pass back a unique identifier to the client. All further calls that need to interact with the object must be passed back to the service.
    1. The token is a GUID so it should be virtually impossible for any other client application to accidentally request access to a data object it didn’t instantiate.
  3. There is a DisposeConnection method. This should be called when the client Disposes one of the WcfDb* objects to properly clean up the connection on the host.
  4. Properties are separated in to separate Get & Set methods. This is due to the fact that the first incarnation of this was as an Asp.Net web service. From what I understand you can decorate the separate Get & Set sections of a Property with the [OperationContract] attribute in WCF. However, I chose not to rewrite these sections at this time.
  5. Overloaded methods aren’t allowed in web services. In the original web service version of this provider, I got around this problem by creating multiple methods with different names for the overloads. (ExecuteReader & ExecuteReaderWithBehavior)

IDataReader

The data reader is one area where I deviated from the model of mapping the contract 1:1 to the data provider interface. An IDataReader object has lots of methods like GetName, GetDecimal, GetDouble, etc. which retrieve metadata or the actual value for a single field at a time. These methods are likely to be called more frequently than any other methods in this contract.

For performance purposes I chose not to have this handled by the service. Instead I added the following method to the service.

  129 [OperationContract]

  130 DataTable GetCurrentReaderRecord(string token);

After reading a record on the WcfDataReader will retrieve the record with this method. The returned DataTable includes all the data (along with metadata) for the current record. All calls on the WcfDataReader which needs individual field information will retrieve the values from this DataTable.

Source Code

Previous: Architecture

Next: Service

 

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>