Using ASP.NET MVC and NHibernate (Part 1)

In this article I’m going to cover how to install and configure NHibernate and use it in a ASP.NET MVC application. This is the first part of a series of articles which demonstrates how to set up NHibernate for a .Net Application.

 

 mvc-logo-landing-page  

+

NHLogoSmall

 

What is NHibernate?

NHibernate is an Object-Relational Mapper (ORM) for .Net which allows object-oriented models to be mapped to a relational database. As you will see in this article, NHibernate will takes care of most of the tasks related to the persistent layer. You can learn more about NHibernate from the NHibernate Community Site.

You can download the latest version of NHibernate from SourceForge. The code examples of this article are based on NHibernate 2.1.1 (Which is the most current version at the moment of writting this post).

 

Install NHibernate

Download and unzip the NHibernate in your computer. Thats it, NHibernate installed.

 

Create the ASP.NET MVC project.

Create a new ASP.NET MVC application and make sure to create a test project.

Add two new Class Library Projects to your solution: Infrastructure and Core (to we can keep everything well organized).

In the Core project, add a reference to the NHibernate assembly.+

 

The Database

For this example we are going to create a model of Posts and Categories, this is a very simple model that will help us to understand how NHibernate works: one blog post can be in one or more categories, and one category can hold zero or more than zero posts:

PostsCategories Model

We will use SQL Server 2008 Express Edition to create our database, another option is to create our models in Visual Studio and command NHibernate to create the database for us, but for this case we will manually create the database.

 

Creating the Model

The next step is to create our Model which is an object-oriented representation of our database, we will use the Class Designer of Visual Studio to create it:

PostsCategories Model

 

Repositories

A repository allows us to create, select, update and delete our objects, a repository is independed of the database. For this tutorial we need to create two repositories: PostRepository and CategoryRepository. Both repositories will implement the following interface:

IRepository.cs

   1: using System;

   2: using System.Collections.Generic;

   3: using System.Linq;

   4: using System.Text;

   5:  

   6: namespace Core

   7: {

   8:     public interface IRepository<T>

   9:     {

  10:         void Save(T entity);

  11:         void Update(T entity);

  12:         void Delete(Guid id);

  13:         T GetById(Guid id);

  14:         T GetAll();

  15:     }

  16: }

To create our repositories we first need a helper class to create a NHibernate session to our database:

NHibernateHelper.cs

   1: using System;

   2: using System.Collections.Generic;

   3: using System.Linq;

   4: using System.Text;

   5: using NHibernate.Cfg;

   6: using NHibernate;

   7:  

   8: namespace Core.Domain.Repositories

   9: {

  10:     public class NHibernateHelper

  11:     {

  12:         private static ISessionFactory _sessionFactory;

  13:  

  14:         private static ISessionFactory SessionFactory

  15:         {

  16:             get

  17:             {

  18:                 if (_sessionFactory == null)

  19:                 {

  20:                     var configuration = new Configuration();

  21:                     configuration.Configure();

  22:                     _sessionFactory = configuration.BuildSessionFactory();

  23:                 }

  24:                 return _sessionFactory;

  25:             }

  26:         }

  27:  

  28:         public static ISession OpenSession()

  29:         {

  30:             return SessionFactory.OpenSession();

  31:         }

  32:     }

  33: }

 

Next, we create the repositories:

PostRepository.cs

   1: using System;

   2: using System.Collections.Generic;

   3: using System.Linq;

   4: using System.Text;

   5: using Core.Domain.Model;

   6: using NHibernate;

   7: using NHibernate.Criterion;

   8:  

   9: namespace Core.Domain.Repositories

  10: {

  11:     public class PostRepository: IRepository<Post>

  12:     {

  13:         #region IRepository<Post> Members

  14:  

  15:         void IRepository<Post>.Save(Post entity)

  16:         {

  17:             using (ISession session = NHibernateHelper.OpenSession())

  18:             {

  19:                 using (ITransaction transaction = session.BeginTransaction())

  20:                 {

  21:                     session.Save(entity);

  22:                     transaction.Commit();

  23:                 }

  24:             }

  25:         }

  26:  

  27:         void IRepository<Post>.Update(Post entity)

  28:         {

  29:             using (ISession session = NHibernateHelper.OpenSession())

  30:             {

  31:                 using (ITransaction transaction = session.BeginTransaction())

  32:                 {

  33:                     session.Update(entity);

  34:                     transaction.Commit();

  35:                 }

  36:             }

  37:         }

  38:  

  39:         void IRepository<Post>.Delete(Guid id)

  40:         {

  41:             using (ISession session = NHibernateHelper.OpenSession())

  42:             {

  43:                 using (ITransaction transaction = session.BeginTransaction())

  44:                 {

  45:                     session.Delete(id);

  46:                     transaction.Commit();

  47:                 }

  48:             }

  49:         }

  50:  

  51:         Post IRepository<Post>.GetById(Guid id)

  52:         {

  53:             using (ISession session = NHibernateHelper.OpenSession())

  54:                 return session.CreateCriteria<Post>().Add(Restrictions.Eq("Id", id)).UniqueResult<Post>();

  55:         }

  56:  

  57:         Post IRepository<Post>.GetAll()

  58:         {

  59:             throw new NotImplementedException();

  60:         }

  61:  

  62:         #endregion

  63:     }

  64: }

CategoryRepository.cs

   1: using System;

   2: using System.Collections.Generic;

   3: using System.Linq;

   4: using System.Text;

   5: using Core.Domain.Model;

   6: using NHibernate;

   7: using NHibernate.Criterion;

   8:  

   9: namespace Core.Domain.Repositories

  10: {

  11:     public class CategoryRepository: IRepository<Category>

  12:     {

  13:         #region IRepository<Category> Members

  14:  

  15:         void IRepository<Category>.Save(Category entity)

  16:         {

  17:             using (ISession session = NHibernateHelper.OpenSession())

  18:             {

  19:                 using (ITransaction transaction = session.BeginTransaction())

  20:                 {

  21:                     session.Save(entity);

  22:                     transaction.Commit();

  23:                 }

  24:             }

  25:         }

  26:  

  27:         void IRepository<Category>.Update(Category entity)

  28:         {

  29:             using (ISession session = NHibernateHelper.OpenSession())

  30:             {

  31:                 using (ITransaction transaction = session.BeginTransaction())

  32:                 {

  33:                     session.Update(entity);

  34:                     transaction.Commit();

  35:                 }

  36:             }

  37:         }

  38:  

  39:         void IRepository<Category>.Delete(Guid id)

  40:         {

  41:             using (ISession session = NHibernateHelper.OpenSession())

  42:             {

  43:                 using (ITransaction transaction = session.BeginTransaction())

  44:                 {

  45:                     session.Delete(id);

  46:                     transaction.Commit();

  47:                 }

  48:             }

  49:         }

  50:  

  51:         Category IRepository<Category>.GetById(Guid id)

  52:         {

  53:             using (ISession session = NHibernateHelper.OpenSession())

  54:                 return session.CreateCriteria<Category>().Add(Restrictions.Eq("Id", id)).UniqueResult<Category>();

  55:         }

  56:  

  57:         Category IRepository<Category>.GetAll()

  58:         {

  59:             throw new NotImplementedException();

  60:         }

  61:  

  62:         #endregion

  63:     }

  64: }

As you can see, is in the repositories where we put the code to call the NHibernate methods, we do it by creating a Session object first.

 

The history so far…

Before continuing, lets review what have we done so far:

  1. We created a Core project with a reference to the NHibernadte.dll assembly.
  2. In the Core project, we created two classes that represent our model: “Post.cs” and “Category.cs”, the post class has collection of categories.
  3. We created two repositories to save, update, delete and select objects of our model.

The Mappings

Now its time to do some work in our Infrastructure project where will map our model to our database, in NHibernate we do this with XML files. There is a naming convention that we should follow for the map files: [ClassName].hbm.xml.

We will create two new files: Category.hbm.xml and Post.hbm.xml. The content of each file maps a class to a table, and a propery to a column, you also specify the data types. For the first part of this tutorial we need to create the Category.hbm.xml file:

   1: <?xml version="1.0" encoding="utf-8" ?>

   2: <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"

   3:                                     namespace="Core.Domain.Model"

   4:                                     assembly="Core">

   5:  

   6:   <class name="Category" table="Categories" dynamic-update="true">

   7:     <cache usage="read-write"/>

   8:     <id name="Id" column="Id" type="Guid">

   9:       <generator class="guid"/>

  10:     </id>

  11:     <property name="Name" length="100"/>

  12:   </class>

  13: </hibernate-mapping>

IMPORTANT: Set the build action of each map file to “Embedded Resource”, this way NHibernate can find the correct file in the  assembly.

Configure it

We are almost ready, the next step is to set the database connection and some NHibernate parameters. The configuration should be in a “hibernate.cfg.xml” file (Set the build action of this file to “Embbeded Resource”). NHibernate has a special “Lazy-Loading” feature for dynamic proxy systems, and we need to add  the following references to the Infrastructure project to support it:

  • Castle.Core
  • Castle.DynamicProxy2
  • NHibernate.ByteCode.Castle.dll

Then create the following XML configuration file:

hibernate.cfg.xml

   1: <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">

   2:   <session-factory>

   3:     <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>

   4:     <property name="connection.connection_string">server=.\SQLExpress;database=NHibernate101;Integrated Security=true;</property>

   5:     <property name="show_sql">true</property>

   6:     <property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property>

   7:     <property name="cache.use_query_cache">false</property>

   8:     <property name="adonet.batch_size">100</property>

   9:     <property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>

  10:     <mapping assembly="Infrastructure" />

  11:   </session-factory>

  12: </hibernate-configuration>

Line # 9: Hibernate uses a lazy loading feature , you can find out more about NHibernate lazy load here.

 

Test it

Now it is time to test our NHibernate configuration!!, lets add some fields to our “Categories” Table, for this we need to reference to the NHibernate assebmly and copy the hibernate.cfg.xml to the test poject.

Add the following references:

  • Castle.Core
  • Castle.DynamicProxy2
  • Infrastructure
  • NHibernate
  • NHibernate.ByteCode.Castle

And add the following test method:

   1: [TestMethod]

   2:         [DeploymentItem("hibernate.cfg.xml")]

   3:         public void CanCreateCategory()

   4:         {

   5:             IRepository<Category> repo = new CategoryRepository();

   6:             Category category = new Category();

   7:             category.Name = "ASP.NET";

   8:  

   9:             repo.Save(category);

  10:  

  11:         }

 

Run the test project and our CanCreateCategory test method should pass the test (hopefully):

Test

 

Now lets check the database to see the new category just added:

 Database

 

Download source code of PART 1

In the next part of this tutorial we will complete the model and the unit tests, then we will create our ASP.NET MVC application.

Advertisements
Comments
17 Responses to “Using ASP.NET MVC and NHibernate (Part 1)”
  1. sokhanh03 says:

    you can upload Database?

  2. h.wasef says:

    Great Article Thanx

  3. Thanks for the article, I’ve downloaded your solution although I haven’t yet got it working..
    Thanks,

  4. 苏志 says:

    你好,谢谢你的文章!

  5. Dennis Humes says:

    how about using LINQ with NHibernate? how is this configured?

  6. Anu says:

    Hi,
    I am trying to create a ORM to read two columns from a table of 100 columns.This has to be done across two different applications.
    I am trying to read from a SQL server 2005 application to use it in my MVC project which uses Raven database.
    Is it possible to create the model and mapping just for those two columns or have to map the entire table?
    Can you give me some ideas?
    Can we model views?

    Thanks,
    Anu

  7. Kms says:

    Which version of Visual studio is used to create this tutorial? I have only Visual Studio 2010 express edition. Can I create this example project over that version.

  8. cace says:

    Hi Cesar, I have no permission to download the code example. Can you help?
    regards

  9. django pp says:

    this was the stuff am looking for…:)

Trackbacks
Check out what others are saying...
  1. […] About « Using ASP.NET MVC and NHibernate (Part 1) […]

  2. […]  Using ASP.NET MVC and NHibernate (Part 1) […]

  3. Using ASP.NET MVC and NHibernate (Part 1) « Forerunner-G34…

    Thank you for submitting this cool story – Trackback from Up.VietGeeks.com…

  4. […] this tutorial I get the following error message when running my tests. I can compile successfully.https://forerunnerg34.wordpress.com/2009/11/03/using-asp-net-mvc-and-nhibernate-part-1/#comment-71Failed to queue test run Test Run deployment issue: The location of the file or directory […]

  5. […] Using ASP.NET MVC and NHibernate (Part 1) November 2009 7 comments 3 […]



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: