Reputation: 20050
I am designing a WCF service that accesses some data stored in a database.
The actual access to the DB is handled by some ORM layer (currently NHibernate, but this is an implementation detail).
I am wondering what is the proper design for this sort of scenario?
The naive approach would be something like:
public class ServiceImplementation : IService
{
// NHibernate session
private ISession session;
// service methods that use *session*
}
This is coupled specifically to NHibernate and forces the service class to manage initialization and owning the ORM logic code.
My questions are in particular:
Since this is such a common scenario, i assume some "patterns" / best practices exist.
Most examples that are available online, demonstrate HOW to achieve this (how to use an ORM to access a DB, etc) but not how this should be properly done from a design perspective, on a larger scale.
Upvotes: 2
Views: 112
Reputation: 1708
Assuming you want to initialize only once, you might want to consider setting up your service implementation class with the following attribute:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)]
This will cause your service to hold a single instance in memory, with multiple callers all accessing that instance. The downside is that your code will have to be thread-safe; additionally, you won't be able to call through to a second WCF service (for this, you need Reentrant concurrency).
However, in this scenario, you can hold a class instance in your service which controls the DB/ORM side of things, achieving the decoupling you desire.
Initialization of the DB/ORM can be carried out in the service's constructor.
Note that it is not wise to make use of a static member variable containing DB/ORM functionality. This is because even static values may be reclaimed by the service host given a sufficient period of inactivity.
This is of course only one way to achieve what you want: you might benefit from examining the cost of multiple initialization vs. the P.I.A. of writing thread-safe code. A compromise would be to use InstanceContextMode.PerSession - a single user session would then have the ORM initialized only once, cutting down on initializations if a user is likely to make multiple calls. The overhead of defining and controlling sessions is a minor irritant at best, and one which, given how long I've rambled on already, is outside the scope of this response.
Upvotes: 1