A demonstration for the beginners as how to start with NHibernate in windows form
Introduction
Today, we will get ourself introduce with an Object Relational Mapper (ORM) technology through NHibernate.The main purpose of any ORM technology is to map the data representation from an object model to a relational data model.In this article, we will address the same with the help of NHibernate through an windows application.
Objective
In this article we will perform a simple CRUD operation with Player entity though winfows application and NHibernate
Where to get NHibernate?
Get the latest NHibernate from here
What to do next?
Once downloaded,unzip the zipped file in a suitable folder location.We will find the NHibernate.dll,Log4net.dll under Required_Bins folder.
Step 1: Create the Relational Model
The first step is to create a Player table in the database.So let us execute the below script that will help us to create the Player table in TestDB database.
CREATE DATABASE TestDB
GO
USE [TestDB]
GO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Player]') AND type in (N'U'))
DROP TABLE [dbo].[Player]
GO
CREATE TABLE [dbo].[Player](
[PlayerId] [int] IDENTITY(1,1) NOT NULL,
[PlayerName] [varchar](50) NOT NULL,
[PlayerAge] [int] NOT NULL,
[DOJ] [datetime] NOT NULL,
[BelongsTo] [varchar](50) NOT NULL,
CONSTRAINT [PK_Player] PRIMARY KEY CLUSTERED
(
[PlayerId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Executing the script will create the player table that will look as under

Step 2: Create a Windows Form Application
Next,let's open up VS2010 and create a project of type "Windows Form application"

Step 3: Create the Object Moddel
Now, let us create the Player object model.For doing so, let us create a class file "Player.cs" and add the below attributes to it
using
System;namespace
NHibernateExperiment{
public class Player{
public int PlayerId { get; set; }public string PlayerName { get; set; }public int PlayerAge { get; set; }public DateTime DOJ { get; set; }public string BelongsTo { get; set; }}
}
Step 4:Create an XML Mapping File(names end with .hbm.xml)
An xml mapping class is needed where we need to map maps between .NET-Classes (Objects) and relational data (Database-Tables).In this file we specify as which columns of the relational table will match with which attribute of the object model.
For this, let us right click on the project -> Add -> New item->XML file.Let us name it as named "Player.hbm.xml"

Add the below to it
<?
xml version="1.0" encoding="utf-8" ?><
hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true"><
class name="NHibernateExperiment.Player, NHibernateExperiment" lazy="true"><
id name="PlayerId"><
generator class="native"/></
id><
property name="PlayerName" column ="PlayerName"/><
property name="PlayerAge" column ="PlayerAge"/><
property name="DOJ" column="DOJ"/><
property name="BelongsTo" column="BelongsTo"/></
class></
hibernate-mapping>
Let us visit as what it does.
<
class name="NHibernateExperiment.Player, NHibernateExperiment" lazy="true">
This line indicates which is the Object Model(here Player) and it belongs to the NHibernateExperiment namespace.That means we need to specify a fully qualified class name followed by the namespace
The next attribute tells us whether we want a lazy initialization of our object model.Setting the property value to true will allow it to load lazily and it is rather a good practice.
<
id name="PlayerId"><
generator class="native"/></
id>
PlayerId is a Primary Key and is auto generated field.
<
property name="PlayerName" column ="PlayerName"/>
It says that the column name is "PlayerName" and the corresponding object attribute name is also "PlayerName". If suppose we have given the object attribute name as "OurPlayerName", then the mapping will be
<
property name="OurPlayerName" column ="PlayerName"/>
Likewise, if the column name in the relational model is changed to "Player Name", then the mapping will be
<
property name="PlayerName" column ="Player Name"/>
Hope the mapping section is clear
Step 6: Create a configuration file
We need to tell NHibernate as where the database resides for which we need an app.config file here and it is as under
<?
xml version="1.0" encoding="utf-8"?><
configuration><
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="connection.driver_class">NHibernate.Driver.SqlClientDriver</property><
property name="connection.connection_string">Server=.;database=TestDB;Integrated Security=SSPI;</property><
property name="dialect">NHibernate.Dialect.MsSql2008Dialect</property> <
property name="show_sql">false</property> <
property name='proxyfactory.factory_class'>NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property></
session-factory></
hibernate-configuration></
configuration>
Step 7:
Add a reference to NHibernate.dll to the project

Step 8: Create a Session Factory
NHibernate expects an NHibernate-Session-object for accessing the database.Henceforth, we need to create a Session Factory for this.
Create a class call "SessionFactory.cs" and add the below code to it
using
System;using
System.Reflection;using
NHibernate;using
NHibernate.Cfg;using
System.ServiceModel.Channels;using
System.Configuration;namespace
NHibernateExperiment{
public sealed class SessionFactory {
private static volatile ISessionFactory iSessionFactory; private static object syncRoot = new Object(); public static ISession OpenSession {
get {
if (iSessionFactory == null) {
lock (syncRoot) {
if (iSessionFactory == null)
{
Configuration configuration = new Configuration();
configuration.AddAssembly(Assembly.GetCallingAssembly());
iSessionFactory = configuration.BuildSessionFactory();
}
}
}
return iSessionFactory.OpenSession();
}
}
}
}
Each application should create only one instance of ISessionFactory per database it access since it is very expensive.
Step 9: Design the Windows Form
Design a windows form as under

Write the Functions
(A)Display button function
private
void btnDisplay_Click(object sender, EventArgs e){
try {
GetPlayerInfo();
}
catch (Exception ex){
throw ex;}
}
The GetPlayerInfo() function is define as under
private
void GetPlayerInfo(){
using (ISession session = SessionFactory.OpenSession){
IQuery query = session.CreateQuery("FROM Player");IList pInfos = query.List<Player>(); dgView.DataSource = pInfos;
}
}
Once a new session is being created, we create a new instance of Query for the given query string ("FROM Player").That we convert to the strongly typed entity which is Player here (query.List()). Finally we bind the result to the grid
(B)Insert button function
private
void btnInsert_Click(object sender, EventArgs e){
Player playerData =
new Player();SetPlayerInfo(playerData);
using (ISession session = SessionFactory.OpenSession){
using (ITransaction transaction = session.BeginTransaction()){
try{
session.Save(playerData);
transaction.Commit();
GetPlayerInfo();
}
catch (Exception ex){
transaction.Rollback();
throw ex; }
}
}
}
The SetPlayerInfo() function is define as under
private
void SetPlayerInfo(Player playerData){
playerData.PlayerName = txtPlayerName.Text;
playerData.DOB =
Convert.ToDateTime(dpDOB.Text);playerData.PlayerAge = playerData.DOB.Subtract(
DateTime.Now).Days / 365;playerData.BelongsTo = cmbBelongsTo.SelectedItem.ToString();
}
The Save method (session.Save(playerData)) accepts a transient instance of a persistent class and generates an identifier after saving the record.Commit ends the unit of work and flushes the associated ISession.The record will be rolled back if any discrepancy happens
(C)Update button function
private
void btnUpdate_Click(object sender, EventArgs e){
using (ISession session = SessionFactory.OpenSession){
using (ITransaction transaction = session.BeginTransaction()){
try {
IQuery query = session.CreateQuery("FROM Player WHERE PlayerName = '" + txtPlayerName.Text + "'"); Player playerData = query.List<Player>()[0]; SetPlayerInfo(playerData);
//changes the data session.Update(playerData);
//update the new data transaction.Commit();
//commit the data GetPlayerInfo();
//display the updated record }
catch (Exception ex) {
transaction.Rollback();
throw ex; }
}
}
}
First we get the record that needs to be updated by firing the query.Then set the new value to the Player Entity and finally Update the record and commit it
(D)Delete button function
private
void btnDelete_Click(object sender, EventArgs e){
using (ISession session = SessionFactory.OpenSession){
using (ITransaction transaction = session.BeginTransaction()){
try {
IQuery query = session.CreateQuery("FROM Player WHERE PlayerName = '" + txtPlayerName.Text + "'"); Player playerData = query.List<Player>()[0]; session.Delete(playerData);
//delete the record transaction.Commit();
//commit it GetPlayerInfo();
//display the new collection }
catch (Exception ex) {
transaction.Rollback();
throw ex; }
}
}
}
Delete function is similar to the Update one.First we get the record that needs to be removed by firing the query in the Player Entity and finally Delete the record and commit it
Finally testing it
Looks fine.Right?.So let us run the application by pressing F5.Enter some relevant value to the respective placeholders and click on the "Insert button"
ERROR!!!!!
Unable to load type 'NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu' during configuration of proxy factory class.
Possible causes are:
- The NHibernate.Bytecode provider assembly was not deployed.
- The typeName used to initialize the 'proxyfactory.factory_class' property of the session-factory section is not well formed.
Solution:
Confirm that your deployment folder contains one of the following assemblies:
NHibernate.ByteCode.LinFu.dll
NHibernate.ByteCode.Castle.dll
Since the Lazy loading is on and the reference for that is not set, henceforth is the complain.So let us follow the solution by adding the NHibernate.ByteCode.LinFu.dll which is found under the Required_For_LazyLoading\LinFu

Let us again run the application by supplying proper input
ERROR!!!!!
No persister for: NHibernateExperiment.Player
It failed at session.Save(playerData); line.This happens because the members persisted in the database have to be virtual since we are using lazy loading.So we need to mark the properties of the "Player" Entity as virtual
using
System;namespace
NHibernateExperiment{
public class Player {
virtual public int PlayerId { get; set; } virtual public string PlayerName { get; set; } virtual public int PlayerAge { get; set; } virtual public DateTime DOJ { get; set; } virtual public string BelongsTo { get; set; } }
}
Let us again run the application by supplying proper input.This time it worked as the output is as under(Insert Operation)

Try to do the Update and Delete operation and that will work too.
Conclusion
This is only an introduction for beginners as how to start with NHibernate.There are more to it which we will address in later articles.Hope you enjoyed it.Zip file is attached for your reference.