Introduction
We often need to create a Data Access Layer (DAL), which takes our business objects and performs CRUD (Create, Read, Update and Delete) in physical data store. If you have ever created the DAL you will come to know how tedious it is to do it again and again. Also, it’s very time consuming to map our objects to the relational database. Here comes Object Relational Mapper (ORM).
Object Relational Mapping (ORM) is a technique by which we map our objects in Object Oriented Programming to get mapped to the underlying relational database. For example, if we have a student object with attributes Name, Age, Roll No etc.and a database table name Student with columns Name, Age, Roll no etc. In traditional approach we will run an insert/update/delete/select query with scalar values to perform manipulations in database. But, what if we have the ability to directly save/remove/read/update the student object without thinking about underlying database. The query itself is getting removed.
Why NHibernate?
NHibernate is ORM framework which has the built in capability of concurrency checks, transactions, lazy loading (objects are not initialized until in use) and transparent persistence (allows to change the DAL without changing Domain Model). To download the latest version of NHibernate visit NHibernate.
Let’s see the steps involved in configuring NHibernate to use in ASP .NET. Following are the common steps to be followed.
- Design your database
- Create your class files
- Create Mapping files to map class to database
- Create a Session Factory class
- Configure web.config file to use the datasource
- Create a Service class for CRUD
Design your Database
We start our example by creating a simple database name Students and creating a table name Student with following columns
Note: the Id is auto generated
Create the class file (POCO class)
Plain old CLR objects (POCO means that do not need to inherit from or implement an interface) business entities are mapped into the table entity. We now create a class file with these columns as properties. The Id column will be read only as it is getting generated in the database as identity. Our class file would look like
Public class Student
{
private string name;
private int id;
private DateTime dateofbirth;
private string address;
public int ID
{
get { return id; }
private set { id = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public string Address
{
get { return address; }
set { address = value; }
}
public DateTime DateOfBirth
{
get { return dateofbirth; }
set { dateofbirth = value; }
}
}
Create Mapping files
Once our class files and table design is complete we need to creating a mapping file which tells the framework what column to map with what properties in the class. It’s a simple XML file. The naming format of the file is Student.hbm.xml. Note the hbm in between student and xml.
<?xml version=”1.0″ encoding=”utf-8″ ?>
<hibernate-mapping
xmlns=”urn:nhibernate-mapping-2.2″
namespace=”NHibernate.Demo.Dal”
assembly=”NHibernate.Demo.Dal”>
<class name=”Student” table=”Student” lazy=”false”>
<id name=”ID” column=”id” unsaved-value=”0″>
<generator />
</id>
<property name=”Name”>
<column name=”Name” not-null=”true” />
</property>
<property name=”Address”>
<column name=”Address” not-null=”true” />
</property>
<property name=”DateOfBirth”>
<column name=”DateOfBirth” not-null=”true” />
</property>
</class>
</hibernate-mapping>
From the above mapping we can see that we first need to define the namespace and assembly where our class files are located and have the same namespace and assembly. Next the class tag attribute name takes class name and table attributes the database table name. next the ID tag is the identification section to identify the identity column. It uses reflection to accomplish it so that only database is able to create those ID’s. You see the ID tag is defined above differently. Inside this class tag we define all the properties with property tag, where name is class property and column tag name is the table column name.
We need to change the build action to embedded resource so that it gets embedded in the assembly.
Define a Session Factory Class
This class will read all of the mapping files and configuration data and build a session that will enable you to talk to the database.
public class SessionFactory
{
private static NHibernate.ISessionFactory sFactory;
private static void Init()
{
NHibernate.Cfg.Configuration config = new NHibernate.Cfg.Configuration();
config.AddAssembly(“NHibernate.Demo.Dal”);
sFactory = config.BuildSessionFactory();
}
public static NHibernate.ISessionFactory GetSessionFactory()
{
if (sFactory == null)
{
Init();
}
return sFactory;
}
public static NHibernate.ISession GetNewSession()
{
return GetSessionFactory().OpenSession();
}
}
Configure web.config file to use the datasource
We specify the database details with which we are making connection and the connection string in the web.config file. You also need to add reference to NHibernate.ByteCode.LinFu.dll and LinFu.DynamicProxy.dll which you can find in the NHibernate download.
<configSections>
<section name=”hibernate-configuration” type=”NHibernate.Cfg.ConfigurationSectionHandler, NHibernate”/>
</configSections>
<hibernate-configuration xmlns=”urn:nhibernate-configuration-2.2″>
<session-factory>
<property name=”connection.provider”>
NHibernate.Connection.DriverConnectionProvider
</property>
<property name=”dialect”>
NHibernate.Dialect.MsSql2005Dialect
</property>
<property name=”connection.driver_class”>
NHibernate.Driver.SqlClientDriver
</property>
<property name=”connection.connection_string”>
Data Source=.SQLEXPRESS;
AttachDbFilename=|DataDirectory|QuickDemo.mdf;
Integrated Security=True;
User Instance=True
</property>
<property name=”proxyfactory.factory_class”>NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>
</session-factory>
</hibernate-configuration>
Create a Service class for CRUD
Finally we need a service class which will talk to NHibernate and the datasource to perform operations. Operations like taking the list, inserting new record etc.
public class StudentService
{
public static ICollection<Student> GetAllStudents()
{
using (NHibernate.ISession session = SessionFactory.GetNewSession())
{
return session.CreateCriteria(typeof(Student)).List<Student>();
}
}
public static void Add(Student student)
{
using (NHibernate.ISession session = SessionFactory.GetNewSession())
{
using (NHibernate.ITransaction transaction = session.BeginTransaction())
{
session.Save(student);
transaction.Commit();
}
}
}
}
As you can see there is no single code written for query statements. This is because the NHibernate framework has taken care about the underlying process. NHibernate exposes two interfaces IQuery and ICriteria to perform query operations.
Download complete project here.