NHibernate
NHibernate is an open source Object-Relational Mapping (ORM) tool for the .Net platform… and the existing documentation and tutorials that I could find, whilst plentiful, are not aimed at those new to or inexperienced with ORM. This tutorial is based on using Visual Studio (I used 2008 beta 2) and Sql Server, however the database used is almost immaterial (one of the advantages of using an OR mapper).
If you already know what NHibernate and ORM are and you want to use it but just need to know how? Otherwise, read on.
WTF is ORM?
There is plenty of good stuff out there on what Object-Relational Mapping is, try wikipedia or the intro here (the tutorial is a bit out of date but the explanation is good) or there’s always Google.
However, in a nutshell, ORM is the process of mapping business objects (think OOP) to database relations (read tables). An OR Mapper is a tool that manages this process. There are several different OR Mappers available for .Net however NHibernate seems to have a lot of momentum and a good history as it is based on a port from the original Java version, Hibernate. The reason for using an OR Mapper is that writing SQL sucks, making changes is a pain in the ass and once you’ve started employing some decent OOP practices and are modelling your business domain with real-world objects, you don’t want to cloud your head with SELECTs, JOINs, WHEREs, primary keys, foreign keys and all that RDBMS jazz.
Okay… so what is ORM again?
Imagine you have a simple Contact class (which coincidentally we will do later). Wouldn’t it be nice if you could create a simple tbl_contact, write a little xml file that says “Contact.FirstName maps to tbl_contact.first_name” and then let something else worry about your CRUD (Create, Retrieve, Update and Delete) database logic? All you then have to do is say “Oi NHibernate, Save this Contact for me please”. That’s what you get with NHibernate and many other OR Mappers, it becomes the basis for your “Persistance Layer” or “Data Access Layer” for those who like their OOP terminology. You get to focus on your business objects and “proper programming” and you let NHibernate worry about saving stuff to the database.
Sounds good, show me
Okay so here’s what we’re going to do:
- Download NHibernate
- Create a contacts table
- Create a Contact class in an assembly
- Write a mapping file between the class and table
- Setup a web project for NHibernate
- Use a simple web form to create and save Contacts
Download NHibernate
I’d suggest starting with just the binary zip (2nd link at time of writing). Save it and extract to somewhere you’ll remember.
Create a contacts table
Our contacts are going to be pretty simple, here’s one I made earlier (SQL Server 2000 – you can very easily use any database you’re familiar with just remember to alter some details later) Create a new database and execute the following SQL:
1 2 3 4 5 6 7 | CREATE TABLE tbl_contact ( contact_id BIGINT IDENTITY (1, 1) NOT NULL , first_name VARCHAR(255), last_name VARCHAR(255), email VARCHAR(255), telephone VARCHAR(50) ) |
So we’re going to actually do some coding now, open Visual Studio create a new Class Library (mine’s called ContactDomain) and add a new class called Contact.cs and paste in the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | namespace ContactDomain { public class Contact { private int _contactId; private string _firstName; private string _lastName; private string _email; private string _telephone; public virtual int ContactId { get{ return _contactId; } set{ _contactId = value; } } public virtual string FirstName { get{ return _firstName; } set{ _firstName = value; } } public virtual string LastName { get{ return _lastName; } set{ _lastName = value; } } public virtual string Email { get{ return _email; } set{ _email = value; } } public virtual string Telephone { get{ return _telephone; } set{ _telephone = value; } } public Contact() { } } } |
Write a mapping file between the table and class
This is where the magic happens. It seems the more you can be bothered to read up on mapping files the better. This example is about as basic as you can get but I will add further tutorials to cater for 1:n relationships and other complexities in due course. You can pretty much handle any scenario with mapping files even complex joins (so I’ve read).
To create the mapping file, add an xml file to your project and call it by the same name as your class but with a .hbm.xml extension (I.E. “Contact.hbm.xml”). Paste in the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="ContactDomain" assembly="ContactDomain"> <class name="Contact" table="tbl_contact"> <id name="ContactId" column="contact_id" type="int"> <generator class="identity"></generator> </id> <property name="FirstName" column="first_name" type="String"/> <property name="LastName" column="last_name" type="String"/> <property name="Email" column="email" type="String"/> <property name="Telephone" column="telephone" type="String"/> </class> </hibernate-mapping> |
Save and build the assembly (Ctrl, Shift + B), this will create your /bin/debug/ContactDomain.dll file which we’ll reference in our web project.
Setup a web project for NHibernate
Create a new web project (mine’s called ContactManager). Open your web.config and add the following below the <configuration> tag:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <configSections> <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> </configSections> <nhibernate> <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider" /> <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Dialect" /> <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" /> <add key="hibernate.connection.connection_string" value="Data Source=myServer;Initial Catalog=myDatabase;Persist Security Info=True; User ID=myDbUsername;Password=myDbPassword;" /> </nhibernate> |
Use a simple web form to create and save Contacts
Firstly we need to add a reference to NHibernate.dll, to do this right click on your project, click Add Reference, browse to where you downloaded NHibernate and find /bin/.Net2.0/Nhibernate.dll and click Add.
If there isn’t already a Default.aspx, add one and paste in the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/ xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID="lblFirstName" runat="server" Text="First Name:"></asp:Label><asp:TextBox ID="txtFirstName" runat="server"></asp:TextBox><br /> <asp:Label ID="lblLastName" runat="server" Text="Last Name:"></asp:Label><asp:TextBox ID="txtLastName" runat="server"></asp:TextBox><br /> <asp:Label ID="lblEmail" runat="server" Text="Email:"></asp:Label><asp:TextBox ID="txtEmail" runat="server"></asp:TextBox><br /> <asp:Label ID="lblTelephone" runat="server" Text="Telephone:"></asp:Label><asp:TextBox ID="txtTelephone" runat="server"></asp:TextBox><br /> <asp:Button ID="btnSaveContact" runat="server" Text="Save Contact" OnClick="btnSaveContact_Click" /> </div> </form> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using ContactDomain; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void btnSaveContact_Click(object sender, EventArgs e) { // setup nhibernate configuration NHibernate.Cfg.Configuration config = new NHibernate.Cfg.Configuration(); // add our assembly config.AddAssembly("ContactDomain"); // setup nhibernate session NHibernate.ISessionFactory factory = config.BuildSessionFactory(); NHibernate.ISession session = factory.OpenSession(); // start nhibernate transaction NHibernate.ITransaction transaction = session.BeginTransaction(); // create contact Contact contact = new Contact(); contact.FirstName = txtFirstName.Text; contact.LastName = txtLastName.Text; contact.Email = txtEmail.Text; contact.Telephone = txtTelephone.Text; // Tell NHibernate that this object should be saved session.Save(contact); // commit all of the changes to the DB and close the ISession transaction.Commit(); session.Close(); } } |
Run the web project, fill in the boxes and hit save. You won’t see anything other than the page refresh but if you then query your database you should see you’ve saved a new contact!
There’s plenty more you can do with NHibernate and now we’ve got the setup out of the way you should find it becomes a huge time-saver for your data-driven projects.
Comments
Post a Comment