Your message has been sent.
This article has been saved to your account.
Go to my account
This article has been emailed to your Kindle.
Send this article
Complete the form below to send this article, Different types of Mapping in Nhibernate 2 , to a friend (or to yourself). We will never share your details (or your friend's) with anyone. For more information, read our Privacy Policy.
NHibernate is an open source object-relational mapper, or simply put, a way to rapidly retrieve data from your database into standard .NET objects.
In this article by Aaron B. Cure, Author of NHibernate 2 Beginner's Guide, we will learn how to glue tables and classes that hold our data in the application
(Read more interesting articles on Nhibernate 2 Beginner's Guide here.)
What is mapping?
Simply put, we need to tell NHibernate about the database that we created and how the fields and tables match up to the properties and classes we created. We need to tell NHibernate how we will be assigning Primary Keys, the data types that we will be using to represent data, what variables we will store them in, and so on. You could say this is one of the most important exercises we will perform in our pursuit of NHibernate. Don't worry though, it's pretty easy.
Types of mapping
There are two basic ways to map data for NHibernate: the traditional XML mapping in an hbm.xml file, or the newer "Fluent NHibernate" style, which is similar to the interface pattern introduced with the .NET 3.5 framework (see http://www.martinfowler.com/bliki/FluentInterface.html).
In both cases, we will create a document for each of our tables. We will map each field from our database to the property we created to display it in our class.
XML mapping
XML mapping is undoubtedly the most common method of mapping entities with NHibernate. Basically, we create an XML document that contains all of the information about our classes and how it maps to our database tables.
These documents have several advantages:
- They are text files, so they are small
- They are very readable
- They use a very small number of tags to describe the data
The two biggest complaints about XML mapping is the verbosity of the text and that it is not compiled.
We can handle some of the verbosity by limiting the amount of data we put into the document. There are a number of optional parameters that do not absolutely need to be mapped, but that provide additional information about the database that can be included. We'll discuss more about that in the Properties section.
You should copy the nhibernate-mapping.xsd and nhibernate-configuration.xsd files from the NHibernate ZIP file into your Visual Studio schemas directory (that is C:\Program Files\Microsoft Visual Studio 9.0\Common7\Packages\schemas\xml). This will give you IntelliSense and validation in the .NET XML editor when editing NHibernate mapping and configuration files.
Without compilation, when the database changes or the classes change, it's difficult to detect mismatches until the application is actually executed and NHibernate tries to reconcile the database structure with the mapping classes. While this can be an issue there are a number of ways to mitigate it, such as careful monitoring of changes, writing tests for our persistence layer, using a Visual Studio plugin, or using a code generation tool.
Getting started
The XML mapping document begins like any XML document, with an XML declaration. No magic here, just a simple xml tag, and two attributes, version and encoding.
<?xml version="1.0" encoding="utf-8" ?>
The next tag we are going to see in our document is the hibernate-mapping tag. This tag has an attribute named xmlns, which is the XML namespace that the NHibernate mapping file should be validated against. This is directly related to a version of NHibernate, as each version has its own XML namespace to cover changes in the mapping language.
We can also use this tag to define the namespace and assembly that the class we are mapping resides in. The opening and closing tags for the hibernate-mapping tag are as shown in the following code snippet:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="BasicWebApplication.Common.DataObjects"
assembly="BasicWebApplication">
</hibernate-mapping>
These three properties within the hibernate-mapping tag make up the basic XML mapping document.
Classes
The next tag we need to define in our document is the class tag. This is a KEY tag, because it tells NHibernate two things—the class this mapping document is meant to represent and which table in the database that class should map to.
The class tag has two attributes we need to be concerned with—name and table
<class name="" table="">
</class>
The name attribute contains the fully-qualified POCO (or VB.NET) class that we want to map to, including the assembly name.
While this can be specified in the standard fully-qualified dotted class name, a comma, and then the assembly name, the preferred method is to define the namespace and assembly in the <hibernate-mapping> tag, as shown in the previous code.
The table attribute specifies the table in the database that this mapping file represents. It can be as simple as the name of the table Address or as complex as needed to adequately describe the table.
If you need to include the owner of the table, such as dbo.Address, then you can add the schema attribute as follows:
schema="dbo"
If we were going to map the Address class in our application to the Address table in the database, then we would use a tag as follows:
<class name="Address" table="Address">
</class>
Technically, as the table name is the same as our class name, we could leave out the table attribute.
Properties
We can map properties from our class to fields in the database using the id tag and the property tag. These tags are for the standard fields in the database, not the Foreign Key fields. We'll get to those in a minute.
The id and property tags follow a standard pattern and have a number of optional parameters. They follow the basic format of defining the property on the class that they are mapping to and the data type that is used to represent that data. This will generally look as follows:
<property name="Address1" type="String">
<column name="Address1" length="255" sql-type="varchar"
not-null="true"/>
</property>
This is the fully-verbose method of mapping the properties, and the one I personally use. If something happens to your database, you can re-generate the database from this information. It's also very helpful when you are troubleshooting because all of the information about the data is right there.
Alternately, you can map the property as follows:
<property name="Address1" />
Both methods will provide the same mapping to NHibernate, but as I stated earlier, the more verbose method gives you a lot more flexibility.
One of the optional attributes that I generally use on the id and property tags is the type attribute. With this attribute I can tell NHibernate that I am using a particular type of data to store that information in my class. Adding this data type, our property tag would look as follows:
<property name="Address1" type="String" />
I also like to use the column tag, just to explicitly link the field with the property in the class, but that again is just preference. The previous code is completely adequate.
ID columns
The first property from our class that we want to map is the Id property. This tag has a number of attributes we can optionally set, but the simplest way we can map the Id property is as follows:
<id name="Id">
<generator class="hilo"/>
</id>
This tells NHibernate that we have a property in our class named Id which maps to a field in the database called Id and also that we use the hilo method to automatically generate a value for this field. Simple enough!
An optional attribute that I generally use on the id tag is the unsaved-value attribute. This attribute specifies what value should be returned in a new object before it is persisted (saved) to the database. Adding this attribute, as well as the type attribute we talked about, the code would look as follows:
<id name="Id" type="Int32" unsaved-value="null">
<generator class="hilo"/>
</id>
As long as our field is named Id in the database, we are good to go. But what if it was named id or address_id? This simply wouldn't handle it. In that case, we would have to add the optional column tag to identify it:
<id name="Id">
<column name="address_id"/>
<generator class="hilo"/>
</id>
Now we have mapped our address_id field from the database into a more standard Id property on our class. Some of the additional attributes that are commonly used on the column tag are as follows:
- name: Define the name of the column in the database
- length: The length of the field, as defined in the database
- sql-type: The database definition of the column type
- not-null: Whether or not the database column allows nulls. not-null="true" specifies a required field
Again, these optional attributes simply allow you to further define how your database is created. Some people don't even define the database. They just define the hbm.xml files and use the NHibernate.Tool.hbm2ddl to create a SQL script to do this work!
(Read more interesting articles on Nhibernate 2 Beginner's Guide here.)
Mapping our types
Let's take a few minutes and map the basic fields from the OrderHeader table we created earlier. What we really need to do is map all of the "standard" fields (ints, varchars, datetimes, decimals, and so on) to their .NET counterparts , A touch of class.
Time for action – mapping basic types
Take a look at the following OrderHeader table. We need to map the Number, OrderDate, ItemQty, and Total fields into our OrderHeader class.

-
Open the OrderHeader class . This will be either OrderHeader.cs or OrderHeader.vb. We will use this file for reference while we create our mapping document. Your class should look as follows:
using System;
using System.Collections.Generic;
using System.Text;
namespace Ordering.Data
{
public class OrderHeader
{
#region Constructors
public OrderHeader() { }
public OrderHeader(string Number, DateTime OrderDate,
int ItemQty, decimal Total, Contact BillToContact,
Contact ShipToContact, Address BillToAddress,
Address ShipToAddress): this()
{
this.Number = Number;
this.OrderDate = OrderDate;
this.ItemQty = ItemQty;
this.Total = Total;
this.BillToContact = BillToContact;
this.ShipToContact = ShipToContact;
this.BillToAddress = BillToAddress;
this.ShipToAddress = ShipToAddress;
}
#endregion
#region Properties
private int _id;
public virtual int Id
{
get { return _id; }
set { _id = value; }
}
private string _number;
public virtual string Number
{
get { return _number; }
set { _number = value; }
}
private DateTime _orderDate;
public virtual DateTime OrderDate
{
get { return _orderDate; }
set { _orderDate = value; }
}
private int _itemQty;
public virtual int ItemQty
{
get { return _itemQty; }
set { _itemQty = value; }
}
private decimal _total;
public virtual decimal Total
{
get { return _total; }
set { _total = value; }
}
private IList<OrderItem> _orderItems;
public virtual IList<OrderItem> OrderItems
{
get { return _orderItems; }
set { _orderItems = value; }
}
private Contact _billToContact;
public virtual Contact BillToContact
{
get { return _billToContact; }
set { _billToContact = value; }
}
private Contact _shipToContact;
public virtual Contact ShipToContact
{
get { return _shipToContact; }
set { _shipToContact = value; }
}
private Address _billToAddress;
public virtual Address BillToAddress
{
get { return _billToAddress; }
set { _billToAddress = value; }
}
private Address _shipToAddress;
public virtual Address ShipToAddress
{
get { return _shipToAddress; }
set { _shipToAddress = value; }
}
#endregion
}
}Or in VB.NET, it will look as follows:
Public Class OrderHeader
#Region "Constructors"
Public Sub New()
End Sub
Public Sub New(ByVal Number As String, ByVal OrderDate As _
DateTime, ByVal ItemQty As Integer, ByVal Total _
As Decimal, ByVal BillToContact As Contact, _
ByVal ShipToContact As Contact, ByVal _
BillToAddress As Address, ByVal ShipToAddress _
As Address)
Me.New()
Me.Number = Number
Me.OrderDate = OrderDate
Me.ItemQty = ItemQty
Me.Total = Total
Me.BillToContact = BillToContact
Me.ShipToContact = ShipToContact
Me.BillToAddress = BillToAddress
Me.ShipToAddress = ShipToAddress
End Sub
#End Region
#Region "Properties"
Private _id As Integer
Public Overridable Property Id() As Integer
Get
Return _id
End Get
Set(ByVal value As Integer)
_id = value
End Set
End Property
Private _number As String
Public Overridable Property Number() As String
Get
Return _number
End Get
Set(ByVal value As String)
_number = value
End Set
End Property
Private _orderDate As DateTime
Public Overridable Property OrderDate() As DateTime
Get
Return _orderDate
End Get
Set(ByVal value As DateTime)
_orderDate = value
End Set
End Property
Private _itemQty As Integer
Public Overridable Property ItemQty() As Integer
Get
Return _itemQty
End Get
Set(ByVal value As Integer)
_itemQty = value
End Set
End Property
Private _total As Decimal
Public Overridable Property Total() As Decimal
Get
Return _total
End Get
Set(ByVal value As Decimal)
_total = value
End Set
End Property
Private _orderItems As IList(Of OrderItem)
Public Overridable Property OrderItems() As IList_
(Of OrderItem)
Get
Return _orderItems
End Get
Set(ByVal value As IList(Of OrderItem))
_orderItems = value
End Set
End Property
Private _billToContact As Contact
Public Overridable Property BillToContact() As Contact
Get
Return _billToContact
End Get
Set(ByVal value As Contact)
_billToContact = value
End Set
End Property
Private _shipToContact As Contact
Public Overridable Property ShipToContact() As Contact
Get
Return _shipToContact
End Get
Set(ByVal value As Contact)
_shipToContact = value
End Set
End Property
Private _billToAddress As Address
Public Overridable Property BillToAddress() As Address
Get
Return _billToAddress
End Get
Set(ByVal value As Address)
_billToAddress = value
End Set
End Property
Private _shipToAddress As Address
Public Overridable Property ShipToAddress() As Address
Get
Return _shipToAddress
End Get
Set(ByVal value As Address)
_shipToAddress = value
End Set
End Property
#End Region
End Class
Before we get started, let's create a few folders to make our job a little easier.Right-click on your Ordering.Data project and click on Add New| Folder.

Using the same procedure, create a new folder called Mapping so we can add our hbm.xml mapping files. When you are done, it should look as follows:

Right-click on the Mapping folder and click Add New Item|.

In the Add New Item – Ordering.Data dialog box, select Data as the category, then XML File under the template. Name the template OrderHeader.hbm.xml and click on Add.

Once the new file has been created, it will open in the editor. It should look something like the following screenshot:

The first thing we want to do with our mapping file is to ensure that it gets compiled into our assembly so NHibernate can find it. Right-click on the OrderHeader.hbm.xml file and select Properties.

In the Properties dialog, drop down the Build Auction menu and select Embedded Resource. This will ensure that the file is compiled into our assembly.

Inside our OrderHeader.hbm.xml document, we want to add the actual mapping data. The first thing we need to add is our nhibernate-mapping element. This will become the root element for our document. Under the <?xml version="1.0" encoding="utf-8" ?> tag, add the hibernate-mapping tags. Your document should look as follows:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Ordering.Data.OrderHeader",
assembly="Ordering.Data">
</hibernate-mapping>
The next element that we will need in our mapping document is the class element. This element lets NHibernate know which class in our assembly maps to which table in the database. Add a class tag to map the OrderHeader class to the OrderHeader table as follows:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name=" OrderHeader" table="OrderHeader">
</class>
</hibernate-mapping
Now, we need to map our Id field. Between the opening and closing class tags, add the following code to map our Id field, and let NHibernate know that it's an Identity field by using the native generator class:
<class name=" OrderHeader " table="OrderHeader">
<id name="Id">
<generator class="hilo"/>
</id>
</class>
If you wish, you can also map the field with all the data required to generate the database, as follows:
<id name="Id" type="Int32" unsaved-value="null">
<column name="Id" length="4" sql-type="int" not-null="true"
unique="true" index="PK_OrderHeader"/>
<generator class="hilo" />
</id>
Most programmers opt for the first syntax when they are handcoding, as it is much less to type! However, when I automatically generate these XML documents with a code generator, I opt to include the additional information to help me troubleshoot later (should something go wrong).
Next, we need to map our remaining properties into the class element. Add the Number, OrderDate, ItemQty, and Total properties as follows:
<property name="Number" type="String"/>
<property name="OrderDate" type="DateTime"/>
<property name="ItemQty" type="Int32"/>
<property name="Total" type="Decimal"/>
That should do it! Your OrderHeader.hbm.xml file should look as follows:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Ordering.Data.OrderHeader, Ordering.Data"
table="OrderHeader">
<id name="Id">
<column name="Id"/>
<generator class="native"/>
</id>
<property name="Number" type="String"/>
<property name="OrderDate" type="DateTime"/>
<property name="ItemQty" type="Int32"/>
<property name="Total" type="Decimal"/>
</class>
</hibernate-mapping>
What just happened?
We created an hbm.xml mapping file for our OrderHeader table and included all of the non-Foreign Key fields. By mapping all of the fields, NHibernate now understands which fields from the database we are using in our classes.
Summary
In this article we've learned,how to glue tables and classes that hold our data in the application
If you have read this article you may be interested to view:
About the Author :
Aaron Cure
Aaron Cure is an avid developer, instructor, and innovator. During his 10 years in the military as a linguist and a satellite communications repair technician, he learned that his real love was computer programming.
After various throes with PHP, Classic ASP, VB, and a brief encounter with Java/JSP, he found a real passion for the .NET framework. After searching for a "better way" to carry out database storage and retrieval, Aaron stumbled across the NHibernate framework.
Unsatisfied with the options for interacting with this great framework, he founded the NHibernate Generation project (nhib-gen) on SourceForge to reduce the "barrier to entry" for most developers.
Aaron and his family run a small consulting and web hosting company doing web design and custom software development for various organizations across the country. One of their more interesting projects has been software to control laser cutting machines.
In his spare time, he also enjoys developing projects with his daughters, using everything from Lego NXT (using C# and Bluetooth communications) to the Microchip PIC platform (using JAL and USB). He also collects and restores classic farm tractors, engines, and farm equipment, as well as semi trucks and trailers. He and his family display them at tractor shows, parades, schools, and various other community events.



Post new comment