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:
Introduction
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.
Preperations
First I downloaded the latest source code from CodePlex using the Subversion client TortoiseSVN. Then I added references to the NHibernate, Fluent NHibernate, and LINQ to NHibernate assemblies.
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:
public class Dinner
{
public Dinner()
{
RSVPs = new List<RSVP>();
}
public virtual int DinnerID { get; private set; }
public virtual string Title { get; set; }
public virtual string Description { get; set; }
public virtual DateTime EventDate { get; set; }
public virtual double Latitude { get; set; }
public virtual double Longitude { get; set; }
public virtual string Country { get; set; }
public virtual string Address { get; set; }
public virtual string HostedBy { get; set; }
public virtual string ContactPhone { get; set; }
public virtual IList<RSVP> RSVPs { get; private set;}
public virtual void AddRSVP(string attendeeName)
{
if (dinner.IsUserRegistered(User.Identity.Name)) return;
RSVPs.Add(new RSVP
{
AttendeeName = attendeeName,
Dinner = this
});
}
public virtual bool IsHostedBy(string userName) { … }
public virtual IEnumerable<RuleViolation> GetRuleViolations() { … }
}
The new RSVP class looks as follows:
public class RSVP
{
public virtual int RsvpID { get; private set; }
public virtual Dinner Dinner { get; set; }
public virtual string AttendeeName { get; set; }
}
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:
[Authorize, AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
if (!dinner.IsUserRegistered(User.Identity.Name)) {
RSVP rsvp = new RSVP();
rsvp.AttendeeName = User.Identity.Name;
dinner.RSVPs.Add(rsvp);
dinnerRepository.Save();
}
return Content(“Thanks – we’ll see you there!”);
}
Thanks to our new method, this can now be reduced to:
[Authorize, AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
dinner.AddRSVP(User.Identity.Name);
return Content(“Thanks – we’ll see you there!”);
}
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!
More object-oriented
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.
finally{}
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

July 24th, 2009 13:13
Very interesting, what I would like to see is how you handle the SessionBuilder? Looking forward for the next parts of this post!
July 24th, 2009 13:58
Very nice
July 24th, 2009 15:07
When there will be a continuation?
July 24th, 2009 15:09
Thank you very much. I am also looking forward for the rest of posts.
July 27th, 2009 08:16
Great post, looking forward to the rest of the series!
I wonder what you think of changing the Register action and pushing the if IsUserRegistered down into Dinner?
Controller:
public ActionResult Register(int id) {
Dinner dinner = dinnerRepository.GetDinner(id);
dinner.AddRSVP(User.Identity.Name);
return Content("Thanks – we’ll see you there!");
}
Dinner:
public virtual void AddRSVP(string attendeeName) {
if (dinner.IsUserRegistered(User.Identity.Name)) return;
RSVPs.Add(new RSVP { AttendeeName = attendeeName, Dinner = this });
}
July 28th, 2009 00:02
Thanks everyone for the positive feedback! I will try to post the second part in the beginning of next week.
Thanks for the suggestion Justin! I think this is a very good idea that will further reduce duplication and simplify the controllers. I will update the post
July 30th, 2009 07:04
Congratulations!
Very nice idea.
Some applications become a reference to present a new framework. It seems that NerdDinner is the one for ASP.NET MVC.
NHibernate + Fluent NHibernate + Linq to NHibernate are cool tools for the guys who are looking forward to create DDD like applications.
Just waiting for the next post…
August 1st, 2009 22:33
Good article, waiting eagerly for the next part!
August 3rd, 2009 13:55
NHibernate is a very convenient way to use it in the domain. Less action and more results. I think your information will help a lot. Thank you.
December 3rd, 2009 18:58
Nerd Dinner sounds like a pretty awesome site. I never heard of it before. The code is great, and will come to a dinner soon.