NHibernate: If you want to save time read this first!

I spent three hours trying to get NHibernate (3.0.0.4000) to work. The task at hand was inserting a record in a SQL Server table. This is my first foray into NHibernate and I wanted to get something up and running quickly.

First I spent time reading articles. There was one article that, I must admit, helped me a lot to get to where I am.

The task that I started was to get a feel of NHibernate, the ORM tool that lets you work with databases without having to know much about databases. I have always been a believer in Tom Kyte’s philosophy of keeping the business logic where the data is. That is on the database. I am more comfortable writing PL/SQL code than front-end code. The concept of tiers is not something that I have to deal with in my day to day programming. This changed till we got a product that has multiple layers that have been setup on multiple tiers. One observation I made regarding this product was it was very easy to switch the underlying database. Today we are testing this product with both Oracle and SQL Server.

I felt I had to brush up my skills and work with this new approach.

Tools Used:
1) SQL Server 2008 Express Edition.
2) Visual Studio 2010
3) NHibernate 3.0

I created a new database named NHibDemoTest and created one table. The script to create this table is

USE NHibDemoTest
GO

/****** Object:  Table [dbo].[student]    Script Date: 01/06/2011 13:53:09 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[student](
	[StudentId] [int] IDENTITY(1,1) NOT NULL,
	[FirstName] [nchar](40) NULL,
	[LastName] [nchar](40) NULL,
	[DateOfBirth] [date] NULL
) ON [PRIMARY]

GO

 

The next step is to work on the front-end program. For the purposes of keeping this as simple as possible, I created a console based application, just like what the original author of the above article did.

Create a new project. Set the target framework to 3.5.

Create New Project
VS 2010 New Project

Extract the NHibernate.zip archive that you downloaded. I extracted mine to the c:\ folderAdd references to the NHibernate.dll In addition to NHibernate.dll, you will also need to add references to one of the proxy factory class. This will be present in the Required_For_Lazy_Loading folder. C:\Nhibernate\Required_For_LazyLoading\LinFu

A lot of what NHibernate does is controlled through mapping files. There are two files that we need to focus on. The first file is the app.config file You will need to add a hibernate-cfg section to this file. This section will look like this.

<hibernate-configuration xmlns=”urn:nhibernate-configuration-2.2″>
<session-factory>
<property name=”connection.provider”>
NHibernate.Connection.DriverConnectionProvider
</property>
<property name=”connection.driver_class”>
NHibernate.Driver.SqlClientDriver
</property>
<property name=”proxyfactory.factory_class”>
NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu
</property>
<property name=”connection.connection_string”>
Server=.\SQLEXPRESS;initial catalog=NHibDemoTest;Integrated Security=SSPI;
</property>
<property name=”dialect”>NHibernate.Dialect.MsSql2008Dialect
</property>
<property name=”show_sql”>true</property>
<property name=”connection.isolation”>ReadCommitted</property>
<property name=”use_proxy_validator”>true</property>
<property name=”default_schema”>NHibDemoTest</property>
<mapping assembly=”NhibConsole.Student”/>
</session-factory>
</hibernate-configuration>

This can be validated against the xsd file provided with NHibernate. It is available in the C:\Nhibernate\Required_Bins folder.
The next step is to create a student.hbm.xml file. This is the file that will map your class entities to the database column names.

<?xml version=”1.0″ encoding=”utf-8″ ?>
<hibernate-mapping xmlns=”urn:nhibernate-mapping-2.2″ auto-import=”true”>
<class name=”NhibConsole.Student, NhibConsole” table=”dbo.student” lazy=”true”>
<id name=”studentId” column=”StudentId” unsaved-value=”0″>
<generator class=”identity” />
</id>
<property name=”birthDate” column =”DateOfBirth”/>
<property name=”firstName” column=”FirstName”/>
<property name=”lastName” column=”LastName”/>
<!– We don’t have to specify a column name if its the same
as the variable name –>
</class>
</hibernate-mapping>

Make sure you set the BuildAction property to “Embedded Resource” on the hbm file.
I spent a lot of time in finding this.

Our table has four columns, so we need to create a class with 4 properties. This is the student class.

    public class Student
    {
        public virtual int studentId { get; set; }
        public virtual string firstName { get; set; }
        public virtual string lastName { get; set; }
        public virtual DateTime birthDate { get; set; }

    }

All the properties of this class need to be declared as virtual. Here’s the rest of the code to make this work.

using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;

namespace NhibConsole
{
    public class Student
    {
        public virtual int studentId { get; set; }
        public virtual string firstName { get; set; }
        public virtual string lastName { get; set; }
        public virtual DateTime birthDate { get; set; }

    }
    class consoleDemo
    {
        static void Main(string[] args)
        {

            Student newUser = new Student
{ birthDate =
new DateTime(1980, 07, 31),
firstName = "Harry", lastName = "Potter" };
            //let's save newuser to the database
            try
            {
                using (ISession session = OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        session.Save(newUser);
                        transaction.Commit();
                    }
                    Console.WriteLine("Saved newUser to the database");
                }
            }
            catch (Exception e) { Console.WriteLine(e); }

        }

        static ISessionFactory SessionFactory;

        static ISession OpenSession()
        {
            if (SessionFactory == null) //not threadsafe
            { //SessionFactories are expensive, create only once
                Configuration configuration = new Configuration();
                configuration.AddAssembly(Assembly.GetCallingAssembly());
                SessionFactory = configuration.BuildSessionFactory();
            }
            return SessionFactory.OpenSession();
        }
    }
}

CTRL+F5 at this point should get you going and the first record will be inserted in your student table.

Leave a comment, if you have any questions.