Techniques - DevSource
DevSource: Microsoft Developer Resource DevSource Home Sponsored by Microsoft Home Add Ons Architecture Languages Techniques Using VS Forums
Home arrow Techniques arrow Page 2 - Getting Started with NHibernate
Getting Started with NHibernate
By Shawn Wildermuth

Rate This Article: Add This Article To:

Getting Started with NHibernate - ' What NHibernate Is '
( Page 2 of 4 )

The hard part of using business objects has always been the tedious nature of writing the data access code to serialize business objects to and from a database. It would be great if there were a way to describe our objects' relationships to the database and each other without resorting to writing lots of code. That is where NHibernate comes in.

What is NHibernate?

ADVERTISEMENT

Our friends in the Java world have had an open-source solution for some time in Hibernate. Happily for us in the .NET world, some gracious developers have ported that library to .NET in the form of NHibernate.

NHibernate allows you write your business objects as .NET classes. The NHibernate engine then takes XML mapping files that correspond to your .NET classes and handles the all of the CRUD (Create, Read, Update and Delete) functions for you.

NHibernate loads the XML mapping files at runtime to determine how your objects relate to each other. As Figure 1 shows, you still host your business objects in your own applications, as usual.

The idea behind NHibernate is to simplify the code required to keep objects in a database. NHibernate does not dictate what database you use or is limited to a single database engine. Current versions work with SQL Server and OLE DB compatible databases. To get a real sense of what it does, let's start working with NHibernate.

Working with NHibernate

The major work in NHibernate is simply learning how to set up your own projects, to load and save your objects.

Your First NHibernate Object

To get started, we can create a simple Customer class to hold data about our customer.

This class is a simple example of a .NET class that holds information about a customer.

Customer.cs
using System;
using System.Collections;
using System.Text;

namespace SimpleExample
{
  public class Customer
  {
    string _customerID;

    public string CustomerID
    {
      get { return _customerID; }
      set { _customerID = value; }
    }
    string _companyName;

    public string CompanyName
    {
      get { return _companyName; }
      set { _companyName = value; }
    }
    string _contactName;

    public string ContactName
    {
      get { return _contactName; }
      set { _contactName = value; }
    }
    string _contactTitle;

    public string ContactTitle
    {
      get { return _contactTitle; }
      set { _contactTitle = value; }
    }
    string _phone;

    public string Phone
    {
      get { return _phone; }
      set { _phone = value; }
    }
  }
}

Now to get NHibernate to support serializing the object, we need to write an XML file that describes how the object is stored in the database. Here is an example of the one for the Customer class:

Customer.hbm.xml:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
  <class name="SimpleExample.Customer, SimpleExample" 
         table="Customers">
    <id name="CustomerID" 
        type="String" length="5">
      <generator class="assigned" />
    </id>
    <property name="CompanyName" 
              type="String" length="40"/>
    <property name="ContactName" 
              type="String" length="30"/>
    <property name="ContactTitle" 
              type="String" length="30"/>
    <property name="Phone" 
              type="String" length="24"/>
  </class>
</hibernate-mapping>

This XML document first specifies the class we're mapping. The convention is to call the file with the same name as the file with hbm.xml as the extension. In addition, we store our mapping files within the assembly itself. To do this, we tell the file that it is an embedded resource. You can do this by changing the build action to Embedded Resource, as seen in Figure 2.

Figure 2: Build Action Setting for Mapping File

First is the root element that specifies that this is a hibernate mapping file and the namespace for the document. The first element after the root element specifies the class to be serialized in the database. Its name attribute specifies the .NET class name and assembly to serialize. The table attribute specifies the underlying table in the database.

Within the class element are the id element and property elements. The id element specifies which property on the Customer class is to be used as the primary identifier (e.g. primary key) for the class. The property elements specify all of the other properties on the class which are to be serialized to the database. For both the id and property elements, they have the same attributes, as seen in Table 1.

Table 1: Basic property/id Element Attributes

Attribute Purpose
Name The name of the property on the class to be serialized.
Type A .NET type of the property.
Length The number of characters that the database table can accept for string types.

The property and id elements accept other attributes; but since this is your first NHibernate object, we'll leave those details for later.

Now that we have our class and the mapping file, we can get started using this new class:

using NHibernate;
using NHibernate.Cfg;

// Loads the NHibernate Types to 
// prepare for Serialization
Configuration cfg = new Configuration();
cfg.AddAssembly("SimpleExample");

First, we need to configure the NHibernate system to tell it about the classes we want to serialize. To do this, we create an instance of the Configuration class and add our assembly to the configuration. This loads all the mapping files contained within our assembly.

// Opens a session to NHiberbate to allow
// us to work with objects
ISessionFactory factory = cfg.BuildSessionFactory();
using (ISession session = factory.OpenSession())
{

  // Loads a specific object from the database
  Customer customer = (Customer)
    session.Load(typeof(Customer), "ALFKI");

  // Show the Contact Name of the Contact
  MessageBox.Show(customer.ContactName);

  session.Close();
}

Now that we have the configuration object, we can tell it to open a SessionFactory. A SessionFactory is an object that can create Sessions. Additionally, Sessions are used to load and save your objects.

In this example, we use the session to load a specific instance of the customer object with the key of ALFKI. Underneath the covers, the NHibernate engine uses the mapping table to retrieve the data directly from the table.

But retrieving a single object is not all that interesting. Does NHibernate support retrieving collections?

Object Collections

NHibernate does not require that you load each object individually. It supports the notion of retrieving lists of objects. To load a list of objects, you need to use an ICriteria object. In the simplest case, you can create an ICriteria object for a .NET type and get a list to retrieve all the objects. For example:

// Get a criteria object to retrieve a colleciton
ICriteria custCriteria = 
  session.CreateCriteria(typeof(Customer));

// Get a collection of all the customers
System.Collections.IList custList = custCriteria.List();

// Enumerate the customers
foreach (Customer cust in custList)
{
  theList.Items.Add(cust.CompanyName);
}

Using the Session object, we can create an ICriteria object by specifying its .NET type. If we simply ask this ICriteria object to return the list, it returns all results.

In most cases, you need more than just a list of all objects. You will want to get the list based on some criterion. To allow for this, the ICriteria object supports adding ICriterion objects to use to specify which objects to return. For example:

// Get a criteria object to retrieve a colleciton
ICriteria custCriteria = 
  session.CreateCriteria(typeof(Customer));

// Add search to a criteria 
custCriteria.Add(new EqExpression("ContactTitle", "Owner"));

// Get the list
System.Collections.IList custList = custList = custCriteria.List();

// Enumerate the customers
foreach (Customer cust in custList)
{
  theList.Items.Add(cust.ContactName + " " + cust.ContactTitle);
}

In this example, we add an EqExpression object to the ICriteria object to specify that we want all Customers where the ContactTitle is "Owner". NHibernate has a large number of these expression objects, and they all support the ICriterion interface. Here is a short list of the most common expressions:

Table 2: Common Expressions

  • EqExpression: Does an equal comparison to a literal value for a specific field.
  • LikeExpression: Does a SQL 'LIKE' comparison with a specific field.
  • BetweenExpression: Does a less than and greater than comparison for range checking on a specific field.
  • EqPropertyExpression: Does an equal comparison between two fields.
  • AndExpression: Used to group other expressions.
  • OrExpression: Used to group other expressions.

Now that we can serialize a single type of object in the database, it might be useful to be able to show relationships between objects. Does NHibernate support this as well? Sure it does.



 
 
>>> More Techniques Articles          >>> More By Shawn Wildermuth
 



Microsoft's Future: A Chat With Their CTO, Barry Briggs

Play Video >

All Videos >

Julia explores the Robotics Studio!

Read now >

Messages to Bill Gates!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.