Data access is one of the most important design decisions in software development. Depending on how you design your data access classes, every single modification causes cascading changes throughout your project. Imagine you have a lot of persistent data objects to manage and, for example, you have to change your database. This transition must be done without modifying the source code of your persistent classes. Other problem happens when you add more persistent data collection classes to the system. Of course, you won’t be happy if every time a new basic class is added, a new CRUD class is needed. The last point is programming in respect with the OOP, in other words, programming for the abstractions and not for implementations, with low coupling and high cohesion.
To solve those problems, the project that I’d worked for the last 8 months (Onibus Recife) used a combination of 3 technologies, and this post is about them.
NHibernate is an Object-relational mapping (ORM) solution for the Microsoft .NET platform: it provides a framework for mapping an object-oriented domain model to a traditional relational database. NHibernate’s primary feature is mapping from .NET classes to database tables. NHibernate generates the SQL commands and relieves the developer from manual data set handling and object conversion, keeping the application portable to most SQL databases, with database portability delivered at very little performance overhead.
NHibernate was used exactly for this purpose: create SQL commands and provide database portability.
Generics is a programming feature added in the .NET Framework 2.0 which allow you to define type-safe data structures, without committing to actual data types. This results in a significant performance boost and higher quality code, because you get to reuse data processing algorithms without duplicating type-specific code.
Using Generics, our team was able to use one, and just one, repository class for all of the simple persistent entities. Every time a new entity was add to the project, nothing more than its corresponding .hbm file was needed.
Autofac is a fresh approach to IoC in .NET that fits well with C# 3.0.
The Autofac framework enabled us to inject all classes’ dependencies in just one place. So, when dependences changed, just a few lines of code were modified in a single source code file.
To illustrate those techniques, I’ll use them in a sample and small project.
Imagine a simple Contacts project used to keep your friends’ address, phone number and birthday. The abstraction of a contact is shown below.
In order to persist the Contact class in my SQL Server database, I used NHibernate framework. Due to that, I need an .hbm file for the Contact class and a NHibernate session manager, responsible to manage database access. Because it’s a small and very simple project, I created a simple session manager, shown below.
Now, it’s time for the repository class. Actually, I implemented a repository interface and its implementation. Remember: program for abstractions, not for implementations. Note that they are generic. I did this to provide a single persistent implementation for more than one entity and simplify my life as a programmer. The code of them is listed below.
Now, let’s test our code reading data from the database. For that, I used the following piece of code.
The test passed, so everything is working.
Now imagine that we need another entity class, for example, a User, to restrict the program access with a username and password. All that I have to do is creating the User.cs abstraction and the User.hbm.xml file. I don’t need a new CRUD class for it. I just use the same generic repository that I used for Contact class, saving me a lot of time. Below is the code that I used to retrieve a user from the database.
Note that we must instantiate a new NHibernateRepository with a NHibernateSessionManager as parameter every time we need a new IRepository instance. Probably, in a big project, this line of code will be scattered in a huge number of files and, if that instantiation change for any reason, a lot of files will be modified. That’s what we don’t want. We like when changes are made in just one place and that is the work of Autofac framework.
Take a look of how the same tests are made using Autofac.
The framework will inject all classes’ dependencies in the beginning of the program execution. Later, to instantiate an object, we ask the framework to resolve its type. If its instantiation changed, just the line of code where Autofac register is changed.
In this post, I’ve introduced a combination of NHibernate, Generics and Autofac. With these technologies in hand, I was able to create an extensible persistent layer in a low coupling and high cohesion way as shown in the sample project created.