I added a repository layer to the server-side stack. This is a very important, but invisible addition to the Excido project.
A few weeks ago, I wrote that I really wasn’t happy that the Web API controller could reach all the way down the stack to the Entity Framework layer. I had originally considered this because I want to use Breeze on the client side and the default Breeze configuration on the server side is strongly coupled to Entity Framework. I was going to mitigate this in the future with some asymmetric layering (not the hairstyle). Breeze brings a lot to the table on the client-side and I didn’t want to give that up, but I also wasn’t comfortable with the layering on the server-side.
I knew that Breeze isn’t hard-coded to Entity Framework. In fact, I have used it at work with NHibernate. So, I knew that the data-access could be reconfigured I just didn’t know how hard it would be. It turned out that is isn’t very hard at all. The Breeze website has many sample applications using different combinations of technologies, including several using ASP.Net WebApi with different data sources. Using these as a reference, I was able to put together my own Breeze Context Provider that is independent of Entity Framework.
With control of the Breeze Context Provider, I was able to insert a repository layer between the Breeze Context Provider and Entity Framework isolating Entity Framework from higher stack layers.
Currently, my repository layer doesn’t do anything other than pass the calls straight through to Entity Framework, so one might wonder why I went through all of the trouble to put it in there.
One reason is that both Breeze and Entity Framework are not written by me and I have no control over them. If I wrote my program allowing the different layers direct access to each other, they would very quickly become dependent on each other. If one of the technologies I have no control over changes or goes away or becomes otherwise unusable, I wouldn’t be able to replace that technology without rewriting my whole application.
For example, if hypothetically, a new version of Breeze was released that had awesome new features, but no longer worked with Entity Framework, I wouldn’t be able to use it without also replacing Entity Framework. Replacing two entire layers of the program could prove impossible without a complete re-write.
Another good reason is that I need a place to put business rules. For example, I want to enforce that a creation time-stamp can never be changed. I also want to enforce that expired content cannot be retrieved and I am going to want to have more than one definition of expired.
Since these rules need to be obvious to the end user, it might make sense to implement them on the client side. That’s actually not a bad idea and a user-friendly UI should make it easy for the users to follow the rules. However, my server-side is sitting on the open internet via a public Web API. I can’t be sure that calls made to my back-end are coming from a web client that I’ve written. The business rules will have to be on the server-side even if they are echoed on the client-side. Also, I may want to write a desktop application that uses the same lower layers as my Web API. If I put the business rules too close to the top of the stack, I’ll have to re-write them for every front end I write.
The best place for the business rules is somewhere that all requests must pass. That place is my repository layer. The repository layer will see every request and every update that goes to the data-layer. Since the upper layers no-longer have access to the lower layers, they cannot bypass the repository layer.
I’m enforcing the separation of the layers with dependency injection through interfaces. Each layer expects an instance of the layer below it to be passed to it in its constructor. The constructor parameters are defined using interfaces rather than classes so that any implementation of the interface can be used and the layer will work.
Figure 1 shows that the Web API controller declares in its constructor that it expects an IBreezeContextProvider. It doesn’t know or care how the IBreezeContextProvider interface is implemented, it just cares that it is implemented. As long as the API controller has an instance of an IBreezeContextProvider, it can do it’s job.
The class BreezeContextProvider (notice it doesn’t start with an I) is an implementation of that interface, but it similarly needs an instance of an IRepository<T> to do its job. It declares this in its constructor and does all of its work using whatever implementation is given to it.
In this case, the implementation of that interface is my repository layer.
Likewise, my repository layer requires an implementation of the IDataContext interface to work. The EntityFramework DBContext for my project implements the IDataContext interface and can be used by the repository layer to do it’s job. I can, if I need to, write other implementations of the IDataContext interface and the repository layer would work just as well.
So, if the hypothetical scenario described above I was considering no longer using EntityFramework. If all of the layers were coupled, it would be impossible. With decoupled layers, I need only write a new implementation of IDataContext and the rest of the program will continue working unchanged.
I’m using Unity Container in the Web API project to do automatic dependency injection for me. This allows me to map all of the interfaces in the program to classes in one place. Unity takes care of making sure each layer gets the dependencies it needs. Unity Container was formerly called the Unity Application Block and was maintained by the Microsoft patterns & practices team. It has since become an open-source project.