Proxy Data Provider with WCF – Client
Sunday, August 9, 2009 at 12:26PM This article is a continuation of a longer tutorial. If you haven’t done so already you should read it from the beginning.
Client
Now that we have the service and contract built, we can finally build the client. The client consists of two assemblies, the ClientProxies assembly contains the code to talk to the service. The DbProvider assembly is the actual data provider which will be used by the final application.
ClientProxies
10 public class WcfDataProviderProxy : IWcfDataProvider
11 {
12 private IWcfDataProvider _channel;
13
14 public WcfDataProviderProxy(string host)
15 {
16 string enpointAddress = "net.tcp://" + host;
17 ServiceEndpoint endPoint = new ServiceEndpoint(
18 ContractDescription.GetContract(typeof(IWcfDataProvider)),
19 new NetTcpBinding(),
20 new EndpointAddress(enpointAddress));
21
22 _channel = new ChannelFactory<IWcfDataProvider>(endPoint).CreateChannel();
23 }
This class is quite simple. The constructor takes the host address as a parameter and constructs an IWcfDataProvider Channel. One thing to note is that the endpoint is being hard coded as NetTcpBinding. Usually with WCF this would be configured in the App.Config. However, we can’t allow that for this library. The end client for the data provider will often be out of our control. This forces us to create the endpoint manually.
All the rest of the methods in the proxy class are straight wrappers around calls to the channel.
27 public string CreateConnection(string invariantName)
28 {
29 return _channel.CreateConnection(invariantName);
30 }
31
32 public void SetConnectionString(string token, string connectionString)
33 {
34 _channel.SetConnectionString(token, connectionString);
35 }
Data Provider
The final piece are the actual data provider classes. These are the classes which implement the IDb* interfaces and are used directly by the consuming application.
WcfDbConnection
The data provider starts with the connection. As with all data providers, all connection information must be supplied through the connection string. In our case we actually have two distinct parts to the connection string. It must contain connection information so the provider can talk to the service. It also needs the connection string information the service will use to connect to the database.
To make this example simple, the connection string requires a ServiceHost parameter then an InvariantName parameter. The normal connection string will then follow.
83 private void SetConnectionString(string connectionString)
84 {
85 string tempConnectionString = connectionString;
86 string parameterName;
87 string parameterValue;
88
89 //Get First Parameter which MUST be ServiceHost
90 if (!GetNextConnectionStringParameter(ref tempConnectionString, out parameterName, out parameterValue)
91 || parameterName != "ServiceHost")
92 {
93 throw new Exception("Connection String Must begin with ServiceHost parameter");
94 }
95
96 _host = parameterValue;
97
98 //Get Second Parameter which MUST be InvariantName
99 if (!GetNextConnectionStringParameter(ref tempConnectionString, out parameterName, out parameterValue)
100 || parameterName != "InvariantName")
101 {
102 throw new Exception("Connection String Must have InvariantName as second parameter");
103 }
104
105 _invariantName = parameterValue;
106
107 CreateProxy();
108
109 _provider.SetConnectionString(_token, tempConnectionString);
110 }
After setting the connection string, the provider will instantiate the client proxy class and use it to create a connection on the server. It will store it’s token internally and use it for all future calls to the proxy.
21 private void CreateProxy()
22 {
23 _provider = new WcfDataProviderProxy(_host);
24 _token = _provider.CreateConnection(_invariantName);
25 }
26
27 private string _token;
28 public string Token
29 {
30 get { return _token; }
31 set
32 {
33 _token = value;
34 }
35 }
All other interface calls are pretty much direct wrappers of the proxy class. At this point it’s important to note that the connection string must be set before any other calls are made. If you try to perform anything such as checking the ConnectionState before the proxy is created (connection string set), you will get a null reference exception.
The Command and DataReader classes follow pretty much the same pattern.
Usage
At this point we can now use the data provider much like any other.
30 string connectionString = @"ServiceHost=localhost:4200;InvariantName=System.Data.SqlClient;Data Source=Holly\SQLExpress;Initial Catalog=AdventureWorks;Integrated Security=True;";
31
32 using (IDbConnection connection = new WcfDbConnection())
33 {
34 connection.ConnectionString = connectionString;
35 connection.Open();
36
37 using (IDbCommand command = connection.CreateCommand())
38 {
39 command.CommandText = "select * from [Person].[Contact]";
40
41 using (IDataReader reader = command.ExecuteReader())
42 {
46 while (reader.Read())
47 {
Final Notes
The code presented here shows the method and beginnings of a Data Provider. A more complete implementation will require these same steps to be used to create a WCF wrapper classes for IDataAdapter, IDbDataParameter and other provider specific classes.
Previous: Service
.NET,
Databases in
WCF Data Provider
Reader Comments