NHibernate in Details: Part 2

Introduction

 
A few days ago I wrote an article on “NHibernate in Details” that can be found in the C# Corner website with NHibernate in Details: Part 1 covering the use of popular ORMs such as Hibernate. Within the .Net perspective it is known as “NHibernate”. This article is Part 2 in continuation of that and uses the same sample Employee Projects created in Part 1. So Let's start to understand NHibernate from the basics.
 

NHibernate

 
NHibernate is an ORM framework for mapping a domain model class to a traditional relational database or a kind of Object Relational Mapper that is a port of the popular Java ORM Hibernate. It serves as a persistence layer coupled with a database layer and Plain Old CLR Objects (POCOs). NHibernate relies on .NET reflection and supportive library from NHibernate.dll.
 
Definition according to Wikipedia:
 
“NHibernate is an object-relational mapping (ORM) solution for the Microsoft .NET platform. It provides a framework for mapping an object-oriented domain model to a traditional relational database. Its purpose is to relieve the developer from a significant portion of relational data persistence-related programming tasks. NHibernate is free as open source software that is distributed under the GNU Lesser General Public License. NHibernate is a port of Hibernate. ”.
 

The Saga of Persistence

 
The concept of Software Development revolves around the need for creation of data and the persisting or storage of data, retrieves data from the pool or database in a fast and organized manner. The characteristics of an efficient software development practice is to choose a good software development methodology and design pattern to store data in simple binary or text files on a database or disks. We currently have a variety of formats to save data, such as in CSV, XML and JSON formats. Thus managing data persistence is currently a hot topic.
 
In ASP.Net to save and retrieve data we can use a dataset or data reader but for all these we need to hardcode the SQL query to interact with the database. NHibernate comes to the resue to eliminate the necessity of writing all those queries many times and interact with the database.
 
But the software development concepts are mainly based on the database concepts of persisting data and searching or retrieving of data using a SQL query. But the database management system creates a problem if we start thinking in the context of an object-oriented approach or domain model.
 
An application with a domain model having inheritance, collection classes and composition does not fit with a relational or tabular representation of database. Thus using a .NET application we can define classes having OOP concepts rather than simply using Data Tables. This is in general known as an impedance mismatch or paradigm mismatch (or object/relational structural mismatch) as described in terms of:
  • The problem of granularity.
  • The problem of inheritance and polymorphism.
  • The problem of association.
  • The problem of Identity and so on.
Advantages of NHibernate
  • NHibernate is an ORM framework and Object Relational Mapping tool.
  • It is a framework to map the data of an Object Domain with the data of a Relational Domain.
  • It is used to overcome the problem encountered by a developer to persist data into databases and the need to fetch persistent data from databases.
Why to Choose NHibernate
  • In general the ASP.NET framework uses ADO.NET to deal with the database interaction.
  • The problem with the manual creation of a Data Access Layer (DAL) for interacting with a database system is that a developer needs to do all the database related tasks such as opening the connection, creating a query, executing the query, closing the connection and so on. In other words a developer must be an expert in both, the Object Domain as well as the Relational Domain.
  • The NHibernates comes to the rescue to handle most of the work of persisting objects into the database, thus providing a solution for the problem of impedance mismatch.
  • XML files play an important role in the configuration and mapping of information between objects and relational databases.

NHibernate Architecture in General

 
The NHibernate architecture provides multiple layers in its ORM framework as shown below:
 
NHibernate Architecture
  1. On the top it consists of an ASP.NET or Windows Application layer.
  2. ASP.NET uses persistence objects (POCOs) to interact with SessionFactory, Session, and Transaction interfaces.
  3. Session Objects interact with the ADO.NET API or ODBC / OLEDB to do a query for storing and retrieving data or we can use a standard ADO.NET command for it.
  4. NHibernate has support for interacting with a variety of different databases to store data or persist objects.
Persistent of objects without NHibernate
 
Persistent of objects
 
 
Procedure
  1. The ASP.NET application creates Business Objects.
  2. The Business Objects interact with the DAL to create and formulate a SQL Query.
  3. The DAL interacts with the underlying database using ADO.NET.
  4. All interactions (CRUD operations) are saved into the database for future interaction.
Persistent of objects with NHibernate
 
Persistent of object with NHibernate
 
Procedure
  1. Creates Business Objects
     
    An ASP.NET application creates Business Objects in the form of POCO classes to be persisted.
     
    A POCO / persistent class must have the following characteristics:
      - It has an ID or unique identifier to be used by NHibernate to uniquely identify objects and generate primary keys and so on. 
       
      - It must provide getter and setter methods for all its properties.
       
      - A property must be marked virtual for helping NHibernate to create a proxy.
       
  2. Creation of Configuration Objects
     
    Business Objects (POCOs) interact with the ORM Framework.
       
      - The ORM Framework gets information about the database from the XML files such as web.config or hibernate.cfg.xml.
       
      - The configuration files provide information about the database connection, dialects, Show_Sql query, hbm2sql and so on.
       
  3. Creation of Mapping Information from POCO Objects and Tables
     
    A mapping file for mapping Objects and their relations with the database needs to be created.
       
      - It specifies information about what property of objects are mapped to which tables and columns and how the data of the objects are to be persisted.
       
      - The Mapping file must have a name such as Object name + prefix with “xxxx.hbm.xml”, in other words Employee.hbm.xml.
       
  4. Creation of Session Factory
     
    The NHibernate Framework creates the following object to create a query by itself depending on what CRUD operation is required and saves the objects into the database.
       
      - A configuration object is created.
       
      - A Session Factory is obtained from configuration objects.
       
      - Gets a Session object from the Session Factory.
       
      - Creates Transaction objects.
       
      - Objects are passed to the Session for persisting in the database.
       
      - Commit the Transaction.
This is as shown below:
 
Creation of Mapping Information from POCO Objects
 
Note: For Part 1, refer to NHibernate in Details.
 

Rules/Constraints for developing NHibernate projects

 
    For Mapping with Plain Old CLR Objects (POCOs):
     
    NHibernate Mapping
     
    For NHibernate Mapping with a Database:
     
    Converting SQL database

Converting SQL database types to .NET types

 
It must be useful to know what types of data from a SQL database maps with .NET types. For example: “int of SQL Server became an Integer, whereas a varchar became a String”.
 
This can be understood from the following table:
 
database type
 
Overview of NHIBERNATE objects and interfaces
 
The various Objects and Classes used in NHibernate are:
  1. Configuration Objects
  2. SessionFactory Interface
  3. Session Interface
  4. Transaction Interface
Let's discuss than one by one
 
1. Web.Config: Configuration Objects
 
NHibernate specifies configuration information in the web.config file and uses configuration objects in an aspx page to retrieve configuration information in object form. In web.config the configuration information needs to be specified that helps NHibernate to connect with the specified database and map the resource files assembly, in other words .hbm.xml file.
 
Note: For the code please refer to the article's Part 1 NHibernate in Details.
 
The various sections specified in the web.config file are as shown below:
  1. <configuration>  
  2.   <configSections>  
  3.     <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler,NHibernate"></section>  
  4.    </configSections>  
  5.     
  6.   <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">  
  7.     <session-factory>  
  8.       <property name="hbm2ddl.auto">update</property>  
  9.       <property name="connection.provider">  
  10.         NHibernate.Connection.DriverConnectionProvider  
  11.       </property>  
  12.       <property name="dialect">  
  13.         NHibernate.Dialect.MsSql2008Dialect  
  14.       </property>  
  15.       <property name="connection.driver_class">  
  16.         NHibernate.Driver.SqlClientDriver  
  17.       </property>  
  18.       <property name="connection.connection_string">  
  19.         Data Source=(local);Integrated Security=True; initial catalog=Test  
  20.       </property>  
  21.       <property name="show_sql">  
  22.         true  
  23.       </property>  
  24.       <mapping assembly="EMPNHibernate" />  
  25.     </session-factory>  
  26.   </hibernate-configuration>  
  27.     
  28. <system.web>  
  29.         <compilation debug="true" targetFramework="4.0" />  
  30. </system.web>  
  31. </configuration>  
Sections in Web Config
 
2. Abstract factory pattern: SessionFactory Interface
 
The NHibernate framework uses the abstract factory pattern for creating sessions and using them to persist the objects into the database.
 
It is a factory class that is used in an aspx page to create session objects. The SesionFactory Objects can be created or built from the configuration objects (.cfg.xml) as shown below.
  1. public static ISession OpenSession()  
  2. {  
  3.     var configuration = new Configuration();  
  4.     configuration.Configure();  
  5.     ISessionFactory sessionFactory = configuration.BuildSessionFactory();  
  6.     return sessionFactory.OpenSession();  
  7. }  
Why Sessions From ASP.NET Do Not Work Well
 
Since ASP.NET sessions are stateless in nature and NHibernate requires the use of a single session that can be spreads across the several pages or requests, this statelessness nature of a normal ASP.NET session makes it difficult to maintain and perform transactions in applications.
 
Singleton pattern: NHibernate uses the Singleton pattern to store the session in the user's context and do transactions. The Singleton pattern can be simply created by creating a sealed class having all member methods and variables declared static. This class can have a property called Instance. This class can also have a non-static constructor that has the implementation details.
 
In simple terms we can create a simple class with NHibertnateSession with a static method in it as in the following:
  1. public class NHibertnateSession  
  2. {  
  3.     public static ISession OpenSession()  
  4.     {  
  5.         var configuration = new Configuration();  
  6.         configuration.Configure();  
  7.         ISessionFactory sessionFactory = configuration.BuildSessionFactory();  
  8.         return sessionFactory.OpenSession();  
  9.     }  
  10. }  
This session can also used to manage the second level caching of persistent objects, in other words from EHChache or OSCached, memcached and so on.
 
3. Session Interfaces
 
The Session objects can be created from the SessionFactory created as in the preceding.
 
So when we want to create a session, we just ask the session factory to open a session using:
  1. ISession session = sessionFactory.OpenSession();  
or
  1. ISession session = NHibertnateSession.OpenSession();  
Where NHibernateSession is our Session Factory.
 
For Example: To OpenSession from Session Factory.
  1. ISession session = NHibertnateSession.OpenSession();  
  2. Employee emp = new Employee();  
  3. emp.FirstName = txtName.Text;  
  4. emp.LastName = txtLastName.Text;  
  5. emp.Designation = txtDes.Text;  
  6. session.Save(emp);  
This interface provides methods for persisting objects, creating transactions, performing query operations and so on with NHibernate. NHibernate handles all the interaction with the databases, such as for open, pooling and closing connections and so on.
 
4. Transaction Interfaces
 
The Transaction interface is used to encapsulate our CRUD statements in  "transaction" objects that must begin and be committed in the end.
 
First to start the transaction from a session using begins:
  1. session.BeginTransaction()  
  2.   
  3. Transaction tx = session.BeginTransaction();  
For Example: To use Transaction Interfaces.
  1. public void loadData()  
  2. {  
  3.      using (ISession session = NHibertnateSession.OpenSession())  
  4.       {  
  5.        using (var tx = session.BeginTransaction())  
  6.           {  
  7.               /*** Using Query ***/  
  8.               var employees = session.Query<Employee>().ToList();  
  9.               foreach (var emp in employees)  
  10.               {  
  11.                   Response.Write(emp.FirstName + emp.LastName);  
  12.               }  
  13.               tx.Commit();  
  14.           }                          
  15.         }  
  16.    }  
  • The Transaction API is used by NHibernate to perform a transaction getting the current session of an ISession interface for this HTTP request from SessionFactory.
  • The ISession is closed after the transaction completes, either in the Application_EndRequest event handler in our application class or in an HttpModule before the HTTP response is sent.
  • The is also known as lazy initialization since the ISession is still open when the view is rendered, so NHibernate can load uninitialized objects before performing any transactions.

Hibernate Query Language (HQL) and criteria API

 
NHibernate uses the Hibernate Query Language (HQL) to create a query with the databases. NHibernate also uses an object-oriented query using a criteria API that can be used to formulate type-safe queries.
 
For Example:
  1. var employees = session.CreateCriteria<Employee> ("From Employee").List<Employee>();  
ADO.NET Query with NHibernate
 
NHibernate can also be used to do normal ADO.NET queries as done earlier.
  1. protected void Deleteobjects()  
  2. {            
  3.   ISession session = NHibertnateSession.OpenSession();  
  4.   // Clear the previous entries  
  5.   SqlConnection connection = session.Connection as SqlConnection;  
  6.   SqlCommand command = new SqlCommand("Delete from Employee", connection);             
  7.   command.ExecuteNonQuery();  
  8. }  
This is the end of the Part 2, here I tried to provide basic information about NHibernate and its usefulness in the .Net world of Object Persistence. In Part 3 we will jump into the concepts of Hibernate application development. Please post comments.