Last Saturday, I posted the first part in a series about building an ASP.NET MVC application from the ground up using NHibernate and Ninject. It dealt with setting up the structure of your solution and referencing some 3rd party assemblies.
In part 2, we’re going to set up the persistence object model. The persistence object model is a set of objects that we use to persist (save) data to the database.
Warning: This is a sample application. There are widely varying opinions on the correct structure for these types of applications. As with most advanced subjects in the ALT.NET space, Ayende has some great information on the difference between a persistence object model and a domain model. For the purposes of this series, they’re the same thing.
First, we build the structure of our persistence model as plain old CLR objects (POCO). I like to do this in the Visual Studio class designer. It helps keep me focused on the high-level entities and relationships instead of wandering off to do detailed implementation code.
Here’s the model we’ll start with:
Let’s look at the relationships between courses and sections. We have a one to many relationship from a Course to it’s Sections represented by an ICollection(Of Section) property in Course. We also have a many-to-one relationship from each section back to it’s Course represented by the Course property on Section.
Public Class Course Public Property Sections() As ICollection(Of Section) Get End Get Set(ByVal value As ICollection(Of Section)) End Set End Property End Class Public Class Section Public Property Course() As Course Get End Get Set(ByVal value As Course) End Set End Property 'Other properties here... End Class
public class Course { public ICollection<Section> Sections { get { } set { } } } public class Section { public Course Course { get { } set { } } //Other properties here... }
Now that we have all of that built, there’s a couple of small requirements to use these classes with NHibernate.
Public Class Course Inherits Entity Private m_Sections As ICollection(Of Section) = New HashSet(Of Section) Public Overridable Property Sections() As ICollection(Of Section) Get Return m_Sections End Get Protected Set(ByVal value As ICollection(Of Section)) m_Sections = value End Set End Property End Class
public class Course : Entity { private ICollection<Section> m_Sections = new HashSet<Section>(); public virtual ICollection<Section> Sections { get { return m_Sections; } protected set { m_Sections = value; } } }
This is how I set up all of my collection properties. You can manipulate the contents of the collection, but you can't replace it with another instance without inheriting this class and overriding the property. If you were to make this property readonly, you'd have to configure NHibernate to write to m_Sections using reflection. It's sort of a pain, and completely unnecessary. This is easier and accomplishes the same end result.
Also, notice that we're inheriting from a class called Entity. More on that later.
Let's talk about the database for a minute. Each of these entity classes will eventually become a database table. What will you use for your primary keys? Fabio Maulo has a great post on the different NHibernate primary key generators. He also has this post about why identity columns probably are not the best choice.
So what’s a good choice? Well, that’s a matter of opinion. Thanks to NHibernate, I don’t go spelunking through the database much anymore, so I like guids. You really can use what you like, or rather, what your DBA likes.
Now, where are you going to put these primary keys in your objects? In my opinion, this is really a persistence detail – meaning your objects shouldn’t really be dealing with it. That’s why we’re going to keep it hidden away in the base class. Remember, we’re inheriting from Entity.
Public MustInherit Class Entity Private m_ID As Guid Public Overridable Property ID() As Guid Get Return m_ID End Get Protected Set(ByVal value As Guid) m_ID = value End Set End Property End Class
public abstract class Entity { private Guid m_ID; public virtual Guid ID { get { return m_ID; } protected set { m_ID = value; } } }
That’s it for today’s post. In part 3, we’ll configure NHibernate and set up our database. For homework, we’re going to flesh out the other properties in our persistence model. Check out the source code in Visual Basic.NET or C#.
(Reposted from my blog)