I am developing a WCF service which follows MSDN’s service archetype. That said, I am following most of the guidelines in that article and I have my data and service contracts in separate assemblies in the service layer. The question is that this service is heavily based on transactions between the underlying database and its client applications, so that I have almost one class (data contract) per entity in the database. Since the service layer should not access the DAL directly, I have a set of methods in the business layer which receives parameters passed to the service, instantiates the respective entity from the service layer and communicates with the DAL (Enterprise Library’s DAAB) for CRUD operations. However, I feel that these CRUD operations belong to each of the classes in the service layer, but placing them there would make the service layer call the DAL directly… My questions the are:
1) Is having one data contract per database entity a bad practice?
2) Should the CRUD operations be placed directly on the service layer (thus causing a direct dependence of the service layer to the DAL assembly)? –or–
3) Should I, instead, create one wrapper class for each of the contracts in the business layer and place the CRUD operations there, using (maybe) an interface approach to communicate between layers?
Having a strict requirement of one data contract per database entity would be an artificial limitation. In a simple application where you have database entities and all interactions are individual CRUD operations on those entities, it may hold fine. But in a more complex application, it’s very common to have calls that need to join across many database entities and even update many entities in one batch call (batch or sproc).
I probably wouldn’t access the DAL directly from the service layer. Having a business layer allows you to completely change how you persist the data with minimal churn and also allows you to unit test the business layer directly without having to spin up a service.
Interfaces can help decouple but it’s not a strict requirement. The business layer can define it’s data needs using a contract and you can provide a datasource object (the dal) to the business layer as a delegate that implements an interface – it decouples the layers. That allows you to write the business layer and have it define what data needs it has and then have the DAL implement. That’s opposed to creating the CRUD objects and designing your layers the other way up the stack. Focus on the business problems, define what data it needs to satisfy the business then write a DAL that implements those needs as fast as it can. Design down the stack.
So, in summary, I would focus on building a service that exposes logical operations to the clients, with a business layer that enforces the rules and a data layer that can satisfy those business layer requirements. And while designing those layers, focus on the performance, minimizing roundtrips, and narrow your connection and transaction scope times.