Quantcast
Viewing latest article 2
Browse Latest Browse All 4

NHibernate: Getting started guide

Introduction

For people that don't know what NHibernate is.

"NHibernate is a mature, open source object-relational mapper for the .NET framework.
It's actively developed, fully featured and used in thousands of successful projects."
Source

This "NHibernate: Getting started guide" post will explain the basics and how to use NHibernate with:
  • NHibernate 3.3.2
  • NUnit 2.6.2
  • SQLite 1.0.82
  • NuGet

  • Used techniques and design patterns

  • NHibernate Mapping by code
  • Repository
  • Domain Model
  • Unit testing

  • Source code

    You can find the source code of this post on: https://github.com/gergroen/NHibernate-getting-started-guide

    Post summary

  • Installing NuGet
  • Download NHibernate, SQLite and NUnit with NuGet
  • Create and test a domain model
  • Create and test NHibernate mapping by code
  • Configure NHibernate for SQLite
  • Create and test a NHibernate helper
  • Create and test a repository

  • Installing NuGet

    First install the NuGet Package Manager if it is not installed.

    Download NHibernate, SQLite and NUnit with NuGet

    NHibernate
    Now you can open the "NuGet Package Manager" by clicking with the right mouse button on your project and choose "Manage NuGet Packges..."
    Image may be NSFW.
    Clik here to view.

    Search for "NHibernate" and click on Install.
    Image may be NSFW.
    Clik here to view.

    Two references are added to your project "NHibernate" and "Iesi.Collections".
    "Iesi.Collections" is added because "NHibernate" has a dependency on "Iesi.Collections".

    SQLite
    Start the "NuGet Package Manager" again, search for "System.Data.SQLite" and click on Install.

    NUnit
    Start the "NuGet Package Manager" again, search for "NUnit" and click on install.
    To run the unit tests in Visual Studio you can use tools like ReSharper or Testdriven.net.
    If you don't need to run the unit tests in Visual Studio you can download the "NUnit.Runners" via NuGet.
    "NUnit.Runners" allows you to run the unit tests through the command line or a gui.

    Create and test a domain model

    After downloading all the packages we can start with the domain model.
    First we create a simple "Person" domain model with the properties "Id", "FirstName" and a "LastName".
    Also we include the method "GetFullName();".
    using System;

    namespace NHibernate.GettingStarted.Model
    {
    public class Person
    {
    public virtual Guid Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    }

    public virtual string GetFullName()
    {
    return string.Format("{0} {1}", FirstName, LastName);
    }
    }
    After creating the domain model we create a test class to test the domain model.
    We're using "NUnit" to unit test our domain model.
    using NHibernate.GettingStarted.Model;
    using NUnit.Framework;

    namespace NHibernate.GettingStarted.Test
    {
    [TestFixture]
    public class PersonTest
    {
    [Test]
    public void GetFullNameTest()
    {
    var person = new Person
    {
    FirstName = "Test",
    LastName = "Kees"
    };

    Assert.AreEqual("Test", person.FirstName);
    Assert.AreEqual("Kees", person.LastName);

    Assert.AreEqual("Test Kees", person.GetFullName());
    }
    }
    }


    Create and test NHibernate mapping by code

    You can create the NHibernate mapping for your domain models in different ways. In this example i use NHibernate mapping by code.
    using NHibernate.GettingStarted.Model;
    using NHibernate.Mapping.ByCode;
    using NHibernate.Mapping.ByCode.Conformist;

    namespace NHibernate.GettingStarted.Dao
    {
    public class PersonMap : ClassMapping<Person>
    {
    public PersonMap()
    {
    Id(x => x.Id, m => m.Generator(Generators.GuidComb));
    Property(x => x.FirstName);
    Property(x => x.LastName);
    }
    }
    }
    To see the result of the mapping we create this unit test.
    The test output is the traditional xml NHibernate mapping.
    using System;
    using System.Xml.Serialization;
    using NHibernate.GettingStarted.Dao;
    using NHibernate.Mapping.ByCode;
    using NUnit.Framework;

    namespace NHibernate.GettingStarted.Test
    {
    [TestFixture]
    public class PersonMapTest
    {
    [Test]
    public void CanGenerateXmlMapping()
    {
    var mapper = new ModelMapper();
    mapper.AddMapping<PersonMap>();

    var mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
    var xmlSerializer = new XmlSerializer(mapping.GetType());

    xmlSerializer.Serialize(Console.Out, mapping);
    }
    }
    }

    Test output:
    <?xml version="1.0" encoding="Windows-1252"?> 
    <hibernate-mapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" namespace="NHibernate.GettingStarted.Model" assembly="NHibernate.GettingStarted" xmlns="urn:nhibernate-mapping-2.2">
    <class name="Person">
    <id name="Id" type="Guid">
    <generator class="guid.comb" />
    </id>
    <property name="FirstName" />
    <property name="LastName" />
    </class>
    </hibernate-mapping>

    Configure NHibernate for SQLite

    To configure NHibernate we need to create a "nhibernate.cfg.xml" file and set the Copy to Output Directory to "Copy Always".
    <?xml version="1.0" encoding="UTF-8"?>
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
      <session-factory name="NHibernate.Test">
        <property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
        <property name="connection.connection_string">Data Source=test.db;Version=3;New=True</property>
        <property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
        <property name="show_sql">true</property>
      </session-factory>
    </hibernate-configuration>

    Create and test a NHibernate helper

    Now we create a NHibernate helper class to load the configuration and the mapping to create sessions.
    using System.Collections.Generic;
    using NHibernate.Cfg;
    using NHibernate.Cfg.MappingSchema;
    using NHibernate.Mapping.ByCode;

    namespace NHibernate.GettingStarted.Dao
    {
    public static class NHibernateHelper
    {
    private static ISessionFactory _sessionFactory;
    private static Configuration _configuration;
    private static HbmMapping _mapping;

    public static ISession OpenSession()
    {
    //Open and return the nhibernate session
    return SessionFactory.OpenSession();
    }

    public static ISessionFactory SessionFactory
    {
    get
    {
    if (_sessionFactory == null)
    {
    //Create the session factory
    _sessionFactory = Configuration.BuildSessionFactory();
    }
    return _sessionFactory;
    }
    }

    public static Configuration Configuration
    {
    get
    {
    if (_configuration == null)
    {
    //Create the nhibernate configuration
    _configuration = CreateConfiguration();
    }
    return _configuration;
    }
    }

    public static HbmMapping Mapping
    {
    get
    {
    if (_mapping == null)
    {
    //Create the mapping
    _mapping = CreateMapping();
    }
    return _mapping;
    }
    }

    private static Configuration CreateConfiguration()
    {
    var configuration = new Configuration();
    //Loads properties from hibernate.cfg.xml
    configuration.Configure();
    //Loads nhibernate mappings
    configuration.AddDeserializedMapping(Mapping, null);

    return configuration;
    }

    private static HbmMapping CreateMapping()
    {
    var mapper = new ModelMapper();
    //Add the person mapping to the model mapper
    mapper.AddMappings(new List<System.Type> { typeof(PersonMap) });
    //Create and return a HbmMapping of the model mapping in code
    return mapper.CompileMappingForAllExplicitlyAddedEntities();
    }
    }
    }

    Database schema test
    using System;
    using NHibernate.Tool.hbm2ddl;
    using NUnit.Framework;

    namespace NHibernate.GettingStarted.Dao.Test
    {
    [TestFixture]
    public class SchemaTest
    {
    [Test]
    public void CanGenerateSchema()
    {
    var schemaUpdate = new SchemaUpdate(NHibernateHelper.Configuration);
    schemaUpdate.Execute(Console.WriteLine, true);
    }
    }
    }
    Test output:
    create table Person (
    Id UNIQUEIDENTIFIER not null,
    FirstName TEXT,
    LastName TEXT,
    primary key (Id)
    )

    Create and test a Repository

    With the NHibernateHelper we can create a person repository to save, get, update and delete persons to the SQLite database.First we create a repository interface.
    using System;

    namespace NHibernate.GettingStarted.Model
    {
    public interface IPersonRepository
    {
    /// <summary>
    /// Get person entity by id
    /// </summary>
    /// <param name="id">id</param>
    /// <returns>person</returns>
    Person Get(Guid id);

    /// <summary>
    /// Save person entity
    /// </summary>
    /// <param name="person">person</param>
    void Save(Person person);

    /// <summary>
    /// Update person entity
    /// </summary>
    /// <param name="person">person</param>
    void Update(Person person);

    /// <summary>
    /// Delete person entity
    /// </summary>
    /// <param name="person">person</param>
    void Delete(Person person);

    /// <summary>
    /// Row count person in db
    /// </summary>
    /// <returns>number of rows</returns>
    long RowCount();
    }
    }
    Repository class
    using System;
    using NHibernate.GettingStarted.Model;

    namespace NHibernate.GettingStarted.Dao
    {
    public class NHibernatePersonRepository : IPersonRepository
    {
    public void Save(Person person)
    {
    using (ISession session = NHibernateHelper.OpenSession())
    using (ITransaction transaction = session.BeginTransaction())
    {
    session.Save(person);
    transaction.Commit();
    }
    }

    public Person Get(Guid id)
    {
    using (ISession session = NHibernateHelper.OpenSession())
    return session.Get<Person>(id);
    }

    public void Update(Person person)
    {
    using (ISession session = NHibernateHelper.OpenSession())
    using (ITransaction transaction = session.BeginTransaction())
    {
    session.Update(person);
    transaction.Commit();
    }
    }

    public void Delete(Person person)
    {
    using (ISession session = NHibernateHelper.OpenSession())
    using (ITransaction transaction = session.BeginTransaction())
    {
    session.Delete(person);
    transaction.Commit();
    }
    }

    public long RowCount()
    {
    using (ISession session = NHibernateHelper.OpenSession())
    {
    return session.QueryOver<Person>().RowCountInt64();
    }
    }
    }
    }
    Repository test
    using System.IO;
    using NHibernate.GettingStarted.Model;
    using NHibernate.Tool.hbm2ddl;
    using NUnit.Framework;

    namespace NHibernate.GettingStarted.Dao.Test
    {
    [TestFixture]
    public class NHibernatePersonRepositoryTest
    {
    private IPersonRepository _personRepo;

    [SetUp]
    public void CreateSchema()
    {
    DeleteDatabaseIfExists();

    var schemaUpdate = new SchemaUpdate(NHibernateHelper.Configuration);
    schemaUpdate.Execute(false, true);

    _personRepo = new NHibernatePersonRepository();
    }

    [Test]
    public void CanSavePerson()
    {
    _personRepo.Save(new Person());
    Assert.AreEqual(1, _personRepo.RowCount());
    }

    [Test]
    public void CanGetPerson()
    {
    var person = new Person();
    _personRepo.Save(person);
    Assert.AreEqual(1, _personRepo.RowCount());

    person = _personRepo.Get(person.Id);
    Assert.IsNotNull(person);
    }

    [Test]
    public void CanUpdatePerson()
    {
    var person = new Person();
    _personRepo.Save(person);
    Assert.AreEqual(1, _personRepo.RowCount());

    person = _personRepo.Get(person.Id);
    person.FirstName = "Test";
    _personRepo.Update(person);

    Assert.AreEqual(1, _personRepo.RowCount());
    Assert.AreEqual("Test", _personRepo.Get(person.Id).FirstName);
    }

    [Test]
    public void CanDeletePerson()
    {
    var person = new Person();
    _personRepo.Save(person);
    Assert.AreEqual(1, _personRepo.RowCount());

    _personRepo.Delete(person);
    Assert.AreEqual(0, _personRepo.RowCount());
    }

    [TearDown]
    public void DeleteDatabaseIfExists()
    {
    if (File.Exists("test.db"))
    File.Delete("test.db");
    }
    }
    }

    Useful links:

    Source code
    NHibernate documentation 

    Viewing latest article 2
    Browse Latest Browse All 4

    Trending Articles