(This article was written for version 5.3 - new version 5.5 has been just released and this article will be updated soon)
Introduction
Kerosene is a configuration-less, self-adaptive and dynamic ORM library that as been developed to let you avoid all those external mapping and configuration files, to let you use a more SQL-like syntax from your C# code, to completely support your POCO objects without any modification in their source code, not even by including attributes, and to dynamically adapt to whatever circumstance it may has to face even when the knowledge of the schema and details of your database are not completely known, or when they can change without your complete control.
I encourage you to take a look at the original article about Kerosene, that can be found below in the references section. In this article we have focussed in what we have called the "direct" mode of operation, because we have used links that were created using a connection string.
Instead, this article shows how the Kerosene library has been extended to use WCF to support remote client-server scenarios, which can be summarized as in the next drawing:

You may notice that the image refers to the former name of the library. This name has changed and now it is Kerosene for the reasons explained in the introductory article.
In essence, what we want to handle is a scenario in which the client application is not allowed, for whatever reasons, to connect directly to the database, but rather through an intermediate service that, in turn, is the one in charge of obtaining the results from the real underlying database. Reasons for this can be many: from pure security reasons, to a non-reliable communication channel that impedes the use of direct connections, or even for logging purposes. You can choose your own.
The Basics
So, as we are talking about a WCF scenario, we will have a "server" and a "client". The server is based on a number of elements that have no analogous in the "direct" version, as their mission is basically to host the service, and to instantiate the server objects on your behalf. To the contrary, the client is based in the objects we have already seen in the direct version, and it can be considered as an example on how to extend Kerosene to deal with really complex scenarios.
Also, please note that we are going to use the same database scenario we used to explain the Kerosene basics: the minimalist HR system that was described by the SQL model that appeared in the introductory article. We are not going to reproduce it here.
WCF is a whole world in itself. The library focusses on how Kerosene has been extended to use WCF as the underlying communication mechanism between the client and the server, while trying to interfere with WCF as less as possible. So when you are using it you definitely need to use the App.Config files or similar in both your client and your server, and use the configuration options they provide. I'm not going to go deeper in the WCF details as I'm sure you know much more about it then me.
The Server
The Kerosene WCF server is an instance of a class derived from KServerWCF. Your class should override just one method, the CreateLink() one, which role is to create a link object to execute the commands it is receiving from a given client.
There are no restrictions on the type of link object this method will create. Typically you will create a direct link one to connect to an underlying database, but nothing restricts you to create another WCF link instance to serve as a bridge to another server.
In any case, while creating your server's link object you can use the connection package it will receive from the client, which is stored in its Package property. It holds this package as an instance of the DeepObject class, a dynamic object able to store an arbitrary number of properties you can use to modulate the way that link should be created. You can find more details about this class in the references section below.
The way it works will create a different KServerWCF instance (with its associated link object) per each connection. So a single host application can server many connections simultaneously without having them interfere with each other.
The following example shows how a host application can be coded:
KTypesWCF.AddType( typeof( CalendarDate ) );
KTypesWCF.AddType( typeof( ClockTime ) );
ServiceHost host = new ServiceHost( typeof( MyServer ) );
host.Open();
Console.Write( "\n-Press [Enter] to finish the service host...\n..." ); Console.ReadLine();
try { host.Close( new TimeSpan( 0, 0, 5 ) ); }
catch { host.Abort(); throw; }
The first two lines register the custom types you are going to send through the wire. The reason for this is because you have to tell WCF that it will have to deal with types in the parameters it has not previous knowledge about. Obviously, those types should be serializable in order to be transmitted with WCF. In the example I have used two custom types for the sake of the argument: they are included in the download just as an example, they should not be considered as part of the Kerosene library. You can use your owntypes as you wish.
The second group of lines creates the service’s host, registers your Kerosene’s server derived class with it (named "MyServer"), and opens the service. This way each time the host service receives a new connection it will create an instance of your class to serve it. I’m sorry, there is no easy way to register several types – but it should not be a problem as the CreateLink() method can return a different instance each time customized the way you want, for instance with the aid of the connection package.
The third group of lines merely waits until you press a key to close the service’s host. Obviously, you will want to adapt it to your own needs.
Ok, we have created the service that will host our server objects. Now, let’s see how can we create our own server class. It should derive from the abstract KServerWCF class, and it only has to override the above mentioned CreateLink() method, like this:
public override IKLink CreateLink() {
var connString = "Use your favorite connection string here";
var link = new KLinkDirectSQL( connString );
link.AddParameterTransformer<CalendarDate>( x => CalendarDate.ToDateTime( x ) );
link.AddParameterTransformer<ClockTime>( x => x.ToString() );
return link;
}
In this case we have created a direct link adapted for Microsoft SQL server (as this is the one included in the library as an example). We have used a regular connection string to instantiate it, as you may recall from the explanations of Kerosene basics, but the nice thing is that we could have built it using the contents in the connection package.
Also, it is important to register the "transformers" this link object may need to use. You may want to recall that they are in charge of translating, for the command’s parameters, the types they are associated with to the appropriate SQL types understood by your database (actually, by the ADO.NET engine Kerosene is using behind the scenes). This is not the same as we did when registering them for WCF serialization: the former is used with the database, the later with the WCF communication channel.
And that’s it. We have now our server prepared to serve the commands and requests it will receive from the clients.
The Client
The client is just a specialized link object, an instance of the KLinkWCF class that, in turn, implements the IKLink interface. Its constructor takes a first argument being an instance of an IKFactory object that, as you can recall, is the one that indicates the "personality" of the database it will connect to. It will be the factory object used to obtain the appropriate parser to translate your dynamic expression into the syntax this database will understand, among other interesting things.
Once you have instantiated this object you can use its
ProxyConnect() method to start the connection with the server. This method takes two arguments: the first one is a string with the endpoint that WCF will use to locate the service host, as it is specified in the
App.Config file of your client application, and a second an optional argument being the connection package discussed above. There is also the
ProxyDisconnect() method that, as its name implies, closes the connection created with the server and frees all its resources. These methods are virtual ones, so you can override them if needed (for instance for logging purposes).
There is a second constructor which takes three arguments: the IKFactory mentioned above, a string with the endpoint, and the optional connection package. In this case, it will start the connection automatically and you won’t have to start it manually. Let’s see an example:
KTypesWCF.AddType( typeof( CalendarDate ) );
KTypesWCF.AddType( typeof( ClockTime ) );
dynamic package = new DeepObject();
package.Login = "MyLogin"; package.Password = "MyPassword";
var endpoint = "Your_EndPoint";
var factory = new KFactorySQL(); var link = new KLinkWCF( factory, endpoint, package )
As happened with the server, our first task is to register with the WCF machinery the custom types we want to send through the wire. Our second task is to create the connection package – as said before, it is optional, so if you don’t want to use it just set it to null. You can add to it as many properties as needed, as far as their values are serializable. Then we have instantiated the factory. Finally, we have created the link client by using the second override of its constructor, which creates and opens the connection with the server on your behalf.
Once you have this link object you can use it as you had used its direct version cousin. Indeed all the tests included in the download don't make any differences and just use an IKLink reference. Please refer to the examples and discussions in the Kerosene’s introductory article for more details.
A note about security: the assumption is that if you need to secure the communication between your server and your client, you will use the facilities WCF provides for it. Or, in the case of the connection package, you would encrypt the values (in a serializable form) before sending them through the wire. For this reasons Kerosene does try to reinvent the wheel and so does not provide any mechanism to secure the traffic between the server and the client.
Some more details
As this new version of Kerosene for WCF has been built to be completely generic regarding the link objects it uses, the above is really everything you need to know for the vast majority of scenarios. Despite of that let me discuss briefly some more few points that will let you face some more complex situations.
Opening and closing the database
The client link object inherits all the database related methods of the IKLink interface. In particular the DbOpen() and DbClose() ones that let you open and close manually the connection the server is using with the underlying database. Kerosene takes care of opening such connection when needed, and closing it afterwards, so these methods are rarely used. But they might be helpful in database very intensive operations for performance reasons.
By the way, the client will never have access to the real database: these methods merely instruct the server to operate on the client's behalf. There is no way you can obtain the IDbConnection the server's link is using, in case it is a direct one, of even there is no way to obtain from the client what type of link object the server has created to serve its demands.
Transactions
Similarly, the client's link object can use the transaction related methods it has inherit from the IKLink interface. But, again, they are merely a bridge to instruct the server's link object to execute, at the server's side, those methods. There is no way you can obtain from the client any transaction-related object.
Regarding to this, just let me remember you have available the TransactionMode and TransactionState properties that let you interrogate the server for its state and the transaction mode it is using. Depending upon the specific implementation, it might even allow you to set the mode to either Database or Scope - but in this later case, the scope is restricted to the server side.
Intercepting the commands
The commands you are going to execute are written and parsed at the client's side. The server will only received the actual SQL code to execute and the list of associated parameters.
At the server, if you wish, you can override the KServerWCF's EnumeratorCreate() and ExecutorCreate() methods in order to parse the SQL text they are receiving, and decide whether to progress with the operation requested or not (for instance by raising the appropriate exception).
Some users have mentioned me that they are overriding those methods for the sake of logging at the server's side.
What's next
The first and obvious thing is to take a look at the examples provided in the download and give them a try.
This version of Kerosene for WCF has also being tested with the new Maps mechanism, an Entity Framework that let you operate at the level of your business entities instead at the level of the records in the database. I do really suggest you to take a look at it and decide whether it is useful for your needs or not.
References
- Kerosene ORM: the original introductory article of the
Kerosene ORM library can be found here: Kerosene Basics.
- DeepObject: the multi-level dynamic class used for the connection packages. It can be found here: DeepObject.
History
- [v5, September 2012]:
Kerosene is the fifth version of this project. Its version for the WCF version has changed to 5 to keep it in track with the version of the main project.
- [v2, May 2011]: The second version of this project. Its focus was to include some improvements and to resolve some bugs.
- [v1, Jan 2011]: The first version that added support for WCF scenarios. It was based in the former KyneticORM project now rebranded as
Kerosene.