Review - NHibernate 2 - Beginner's Guide From PACKT Publishing

I was contacted by PACKT publishing about a month ago and they asked me to review the NHibernate 2 Beginners guide.

The book assumes that the reader has some knowledge of the .NET framework and either C# or VB.Net.

If you are completely new to NHibernate then this book is a great starting point enabling new-bee's to get up and running very quickly. I would have to say that if you have experience using NHibernate then this book will not be for you, as it lack's some of the more advanced concepts and information needed. But as this is a book for beginner's lets put that opinion to one side.

Firstly the book starts off by introducing NHibernate and ORM's in general explaining what NHibernate is and also it's benefits.

Basic database design concepts are then covered demonstrating how to create tables and relationships and then use classes to represent your data. Both Xml and Fluent Nhibernate mapping is covered with examples of how to map o2m, m2m and m2o relationships from your database to your domain model.

The author then goes onto explain the usage of the NHibernate Session and how to plumb in logging using log4net. After some “Have a go hero” tasks where the author encourages the reader to create some simple examples the book swiftly moves on to configuration.

Examples of how to configure NHibernate programmatically and also using XML are explained including the different proxy options for lazy loading.

Unfortunately I felt the chapter on querying does not do enough to explain the difference between eager and lazy loading. Also I felt that the use of constant variables to hold strings relating to field names in order to gain strongly typed query's could have been demonstrated differently. Either Linq2NHibernate or the Nhibernate Lambda Extensions framework would have been a better choice. Basic CRUD (Create, Read, Update and Delete) operations are explained fully with examples.

By far my most favourite chapter in the book was on code generation and even as an NHibernate veteran I really learned a lot. I used to hate code-gen before I read this book, my new favourite code-gen tool is MyGeneration with a customised L99 template – happy days!

All in all I feel that if you are looking to learn NHibernate then there is no better starting place than the NHibernate 2 Beginner's Guide.

NHibernate 2 - Beginner's Guide

Twitter Twitter Twitter Twitter Twitter
June 24, 2010 23:18 by DanWatson

Raven DB – Part 1 – DocumentSession per request with StructureMap

I have been playing with Raven DB of recent and have decided to use it for an application I am writing. Along the way I will write a series of blog posts about it and try to break my relational model mindset.

I am a big fan of the repository and session per request patterns and have been using these when working with NHibernate for the last few years. Whenever I currently implement these patterns with NHibernate I use an IOC container to manage the lifetime of the NHibernate session (per request),  with Raven I decided to do the same to manage the DocumentSession (per request) and also the DocumentStore (singleton).

I am going to make an assumption that as you are reading this you are already familiar with IOC and its general principles.

I use StructureMap as I find it the easiest to work with and also it is as quick as lightening. Firstly we need to manage the lifetime of the DocumentStore. This should only be instantiated once per application so to manage this I wrote a RavenSessionFactoryBuilder which builds the RavenSessionFactory. The RavenSessionFactory accepts an instance of IDocumentStore so I use StructureMap to manage the lifetime of the RavenSessionFactoryBuilder in singleton scope. This means the DocumentStore and the RavenSessionFactory will only be created once per application (first time GetSessionFactory is called – which is basically the first time your application tries to do any kind of document access).

    public class RavenRegistry : Registry
{
public RavenRegistry()
{

ObjectFactory.Configure(x => x.For<IRavenSessionFactoryBuilder>().Singleton()
.Use<RavenSessionFactoryBuilder>());

ObjectFactory.Configure(x => x.For<IDocumentSession>()
.HybridHttpOrThreadLocalScoped()
.AddInstances(inst => inst.ConstructedBy
(context => context.GetInstance<IRavenSessionFactoryBuilder>()
.GetSessionFactory().CreateSession())));
}
}

 

 

    public interface IRavenSessionFactoryBuilder
{
IRavenSessionFactory GetSessionFactory();
}

 

(Please note the Url is set by a custom settings configuration wrapper I wrote and is not part of the Raven Client API)

    public class RavenSessionFactoryBuilder : IRavenSessionFactoryBuilder
{
private IRavenSessionFactory _ravenSessionFactory;

public IRavenSessionFactory GetSessionFactory()
{
return _ravenSessionFactory ?? (_ravenSessionFactory = CreateSessionFactory());
}

private static IRavenSessionFactory CreateSessionFactory()
{
Debug.Write("IRavenSessionFactory Created");
return new RavenSessionFactory(new DocumentStore
{
Url = Settings.DatabaseUrl
});
}
}


Now I needed to manage the DocumentSession and have StructureMap create one instance of this per request. In the RavenRegistry I instructed StructureMap to instantiate a new DocumentSession in HybridHttpOrThreadLocalScoped scope (when used on the web this will create a DocumentSession per http request). StructureMap will construct the DocumentSession by calling on it’s known instance of RavenSessionFactoryBuilder and in turn calling on the instance of RavenSessionFactory to create the DocumentSession by calling the CreateSession method (little bit of a mind bender!).

    public interface IRavenSessionFactory
{
IDocumentSession CreateSession();
}

 

    public class RavenSessionFactory : IRavenSessionFactory
{
private readonly IDocumentStore _documentStore;

public RavenSessionFactory(IDocumentStore documentStore)
{
if (_documentStore == null)
{
_documentStore = documentStore;
_documentStore.Initialise();
}
}

public IDocumentSession CreateSession()
{
Debug.Write("IDocumentSession Created");
return _documentStore.OpenSession();
}
}


For all this code to work correctly our repository’s need to take a constructor argument of  IDocumentSession. I have a base class (PersistentRepository) for all my repositories which in the abstract implementation has a protected IDocumentSession which is instantiated through the constructor.

    public interface IPersistentRepository<T> where T : IPersistable
{
IList<T> GetAll();
T Save(T obj);
T Update(T obj);
void Delete(T obj);
T Get(string id);
T GetFirst();
T GetUnique(Func<T, bool> where);
IList<T> GetRestictedList(Func<T, bool> where);
void DeleteAll(IList<T> objs);
void UpdateAll(IList<T> objs);
void InsertAll(IList<T> objs);
void SaveChanges();
}

 

    public abstract class PersistentRepository<T> : IPersistentRepository<T> where T : IPersistable
{
protected IDocumentSession DocumentSession { get; set; }

protected PersistentRepository(IDocumentSession documentSession)
{
DocumentSession = documentSession;
}
-------------------removed for brevity----------------------
}

 

The UserRepository (and all of my application repositories) are derived from PersistentRepository so now the derived class takes a IDocumentSession as a constructor argument which is passed back down to the base class. So now once you wire in Structuremap to your application every time a repository is used the instantiation of the DocumentSession will be taken care of for you by StructureMap (please note that even if you are calling on two or more different repositories in one http request the same DocumentSession will be used for all instances – perfecto!) .

    public interface IUserRepository
{
void AddUser(User user);
IList<User> GetAll();
}

 

    public class UserRepository : PersistentRepository<User>, IUserRepository
{
public UserRepository(IDocumentSession documentSession) : base(documentSession)
{
}

public void AddUser(User user)
{
Save(user);
SaveChanges();
}
public new IList<User> GetAll()
{
return base.GetAll();
}

}

This is very close to how I currently implement the session per request and repository patterns with NHibernate. In all honesty it was pretty easy to create this implementation of this for use with Raven (due to good design by Ayende rather than my own personal coding skills). Any thoughts or improvements please let me know via comment or email.

Twitter Twitter Twitter Twitter Twitter
June 12, 2010 00:00 by DanWatson