This is the first post in a series of three where I’m going to see how we can change the NerdDinner project to use Fluent NHibernate instead of LINQ to SQL:
NerdDinner.com is a site where you can organize dinner meetings for nerds, but even more, it is a great tutorial to the ASP.NET MVC framework. If you want to learn this framework (you should!) download the free tutorial (186 pages) from the site and get going!
NerdDinner uses LINQ to SQL as a data access layer generator. LINQ to SQL is perfectly suitable for this project, since the domain is small, and not very complex. However in these posts I would like to explore how the project would look using a real Object/Relational Mapper (O/RM). More specifically, I’m going to use Fluent NHibernate.
The existing domain model
Most of the domain model in NerdDinner is auto generated from the database as partial classes by the LINQ to SQL designer. You can find the Dinner and RSVP class in the NerdDinner.Designer.cs file; however since they are auto generated they are not very readable.
The Dinner class is also extended (using partial classes) with additional methods in the Dinner.cs file.
The new domain model
Since most of the existing domain model is auto generated we need to write a new domain model. The new Dinner class looks as follows:
The new RSVP class looks as follows:
If you wonder why every method is marked by virtual, this is a requirement of NHibernate in order to support Lazy-Loading. I explained this in more detail in the post Mapping a Twitter like domain with Fluent NHibernate.
The public interface of the domain model is more or less identical to the existing domain model. However I did make some changes.
Protect thy privates!
One of the changes I made was to make some of the property setters private; DinnerID, RSVPs, and RsvpID. Since the consumer code (the controllers) is not supposed to change to these properties we want to communicate this to our fellow programmers. The next change is also about protecting privates.
New method to add a RSVP to a dinner
To the Dinner class I added a new method called AddRSVP. By using terms from Domain Driven Design, the Dinner entity is the aggregate root of the RSVP entity. This basically means that a RSVP must belong to a Dinner; hence I want the Dinner class to control the list of RSVPs.
This change will help reduce code in the controllers and remove duplication. Previously the creating and adding of RSVPs was done both in the RSVPController.Register and the DinnerController.Create action methods. The Register method is shown below:
Thanks to our new method, this can now be reduced to:
Similar reduction can be done to the Create method. BTW if you wonder what happened to the call to the Save method then we will come back to this in part 3 (teaser!).
As a rule of thumb always try to keep your action methods as simple as possible!
The last change is the removal of the DinnerId property from the RSVP class. This property is purly database related, and does not belong in an object-oriented domain model. You can use the Dinner propety to get the DinnerId.
In my opinion one of the benefits of using an OR/M like NHibernate as supposed to LINQ to SQL is that the domain model is much clearer. When trying to understand a new project one of the best places to start is by looking at the domain. I also did some changes (improvements?) to the domain model to better communicate intent, and to reduce code duplication.
The next step is to tell NHibernate how to map this domain model to the database. This will be explained in the next post where we look at the mapping.
If you liked this post then please shout and kick me