I am thinking on how I could use NHibernate in a remoting scenario (using .NET remoting, WCF, webservices, whatever ...... ), but I can already see some problems which I will likely encounter on my path.
This is how I see the big picture of the application:
Let me explain it in short:
The client application (a rich Windows client for instance) communicates via some kind of technique, be it WCF or the old .NET remoting, with the Service Layer.
This means that the client application calls a (remote) method on the Service Layer to retrieve a Customer for instance. The client can make some changes to that object and later, the client can call the remote 'SaveCustomer' method so that the Service Layer can persist the changes back to the datastore.
In order to do this, the Service Layer uses a Repository that uses NHibernate to retrieve or persist objects.
Note that the Client Application and the Remote service layer use the same Domain Entities. This means that the domain classes need to be [Serializable].
The problem that I will be facing is this:
- Since (N)Hibernate uses its ISession as a UnitOfWork, which keeps track of the objects that have been created, deleted, inserted, the Client Application doesn't know whether it is necessary to perform a remote call to save the entity or not.
(The client application doesn't know anything of some thing called an 'NHibernate Session', and my business object (entity) has no state tracking as well. (In other words: my entity itself doesn't know whether it has been created, changed or deleted).
- The remote method which will save my entity, will use another ISession then the method that has retrieved it. (Remote methods should be stateless, since multiple callers can call the same method. Client x should not know anything of client Y).
The fact that the 'SaveCustomer' method will use another ISession, means that it is possible that NHibernate will perform unnecessary UPDATE statements. This could be problematic if you use an
AuditInterceptor, since this Interceptor will update the LastUpdated, Version, etc... columns in the DB, while this was not necessary. In other words: this leads to wrong information in the database.
How could these problems be tackled:
- For the first problem, you could implement some kind of 'state tracking' in your entities, and add a property which tells you whether the entity has modified , etc...
- Implementing state-tracking in your domain entities may also solve the 2nd problem; in your repository you can check whether you've to Update or Save (for new entities) your entity. However, I don't know yet how this will behave in situations where an entity contains a collection of other entities ...
I'd like to know from other people how they have tackled these kind of problems ? Did you implement some kind of state tracking in your business entities ?
Or, did you choose not to expose your business entities to the client application, and use Data Transfer Objects instead ? If so, how did you map these DTO's to your business classes ?