Thursday, 20 May 2010

Learn NHibernate lesson 1 - setup and basic usage

disclaimer - at the moment, this post is in note format from a workshop I did, I need to it clean up, and add grammar

its an abstraction layered on top of database

ISesssion, unit of work pattern, same as Dataset in ADO.NET

a unit of work consists of:
Open session by getting from session factory
Do some work (session.add, session.delete)
flush the session

getting a session:
sessionfactory.opensession

how does session factory build itself?
uses configuration class to build it
config is throw away class[csharp]
ISessionfactory sf = new Configuration().Configure().BuildSessionFactory();

[/csharp]


vs 2008
if using xml onfig, drop nhibe xsd's in to vs intellisense directory
once hibernate mapping tag in config xml, will be able to use intellinsense for conifg xml[xml]
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembley="DataTransfer" namespace="DataTransfer">

[/xml]


with reference to NHibernate 1.2.1
1. Setup and basic usage pattern
xml config

mapping files tell nhibe how db maps to objects
relies on convention over configuration
case sensitive
default is to use convention which is "classname.hbm.xml"
one for each class, start with class name[xml]

<class name="DataTransfer.Customer, DataTransfer" table="Customer"> (Namepsapce.TypeName, Namespace)

[/xml]


must have an id tag (primary key or composite id)[xml]

<id name="CustomerId" column="CustomerId" type="Int32" unsaved-value="0">
<generator></generator>

</id>

[/xml]


(this tells nhibe how to generate value for the id, native means db will use its own capabilities to gen the id)[xml]

<property name="FirstName" column="FirstName" type="string" length="50" not-null="false"></property>

[/xml]


if no column name specified, nhibe will asume column is same name as property
deploying mapping files

set build action of hbm.xml in vs to embedded resource so they are compiled in to assemblies
using lutz roeders .NET refelctor you can see dissasemblies

all methods in classes should be virtual!

new up new configuration and session[csharp]

NHibernate.Cfg.Configuration config = new NHibernate.Cfg.COnfiguration();
config.configure();
NHibernate.ISessionfactory sf = config.BuildSessionFactory();
NHibernate.ISession session = sessionFactory.OPenSession();

[/csharp]


creating a dataaccess layer

getting an object from db by id[csharp]

public class NHIbernateDataProvider
{
public Datatransfer.Customer GetCustomerByID(int cumstomerId)
{
NHibernate.Cfg.Configuration config = new NHibernate.Cfg.COnfiguration();
config.configure();
NHibernate.ISessionfactory sf = config.BuildSessionFactory();
NHibernate.ISession session = sessionFactory.OpenSession();

//no generic get
return (DataTransfer.Customer)session.Get(typeof(Datatrasnfer.Customer), customerId);
//generic get
return session.Get<Datatransfer.Customer>(customerId);
}
}
[/csharp]


cleaning that up

configuration class only needed long enough to get a session factory[csharp]

using NHIbernate;
using DataTransfer;

public class NHibernateDataProvider
{
public Datatransfer.Customer GetCustomerByID(int cumstomerId)
{
ISessionfactory sf = (new Configuration()).Configure().BuildSessionFactory();
ISession session = sessionFactory.OpenSession();

return session.Get<Datatransfer.Customer>(customerId);
}
}

[/csharp]


test project for dataaccess layer

assume references addded.. and using statementsn included..
providing a connection string for NHibernate and other configuration

NHibernate configuration file belongs in project that is running code.. so needs to be included in the test project

XML File called "hibernate.config.xml"[xml]

<hibernate-configuration xmlns="urn:nhibernate-mapping-2.2">
<session-factory name="MyFavouriteSessionFactory"> (you could have an app that talks to differnt databases by addnig name to the session factory tag)
<property name="connection.provider">...
<property name="connection.connection_string">...
<property name="show_sql">true<property>
<mapping assembly="DataTransfer"/>
</session-factory>

[/xml]


you can see the defaults needed and structure by opening the nhibernate.config.xml that is downlaoded with NHibernate..

it includes things like query substitutionns, command timeout, drivers and other useful stuff..[csharp]

[TestFixture]
public class tests
{
[test]
public void CanGetCustomerById()
{
DataAccessLayer.NHibernateDataProvider provider = new DataAccessLayer.NHibernateDataProvider();
Assert.AreEqual(1, provider.GetCustomerId(1).CUstomerId);
}
}

[/csharp]


Show SQL
adding the <property name="show_sql">true<property> to your config file qill echo the sql statement (eg console output). so in the html report from MBUnit you wil see the sql generated by NHIbernate in the test results.

nhibernate generates parametirised sql so that sql server can generate cached execution plans. its also protection from sql injection