Localizable entities with Nhibernate Part 1

In a recent project I face the need to localize some entity with nhibernate. First of all I found this interesting post of Ayende that show an interesting solution, but it does not fits well in my project. I need a localization scheme with these features.

  • Orthogonal to the user, and completely transparent
  • The user should be able to change localization text
  • The user can choose whathever language he desires, if no suitable localization exists the entity must returns a default localization
  • The user can add a new localization language for the entity even if the language is not actually present.

At first these features seems very complicated, and I begin to work on a possible scheme that satisfies all of them. First of all the concept of current language should be orthogonal to the user, it means that the user should ask nhibernate to load an entity without worrying of the language. This kind of problems can be solved by the Registry pattern from Fowler (POEAA). This pattern description states: “A well-known object that other objects can use to find common objects and services”, this seems to me a suitable pattern to store the concept of “Current Language”. First of all I create the interface of my Registry in another assembly.

public interface IRegistry {
LangCode CurrentLangCode { get; set;}
LangCode DefaultLangCode { get; set;}

As you can see this registry has only two property that can be used to get/set the current language and the default language, both of them stored as a custom LangCode object. I prefer to use a LangCode custom object because I’m working with a legacy database that stores lang code strings with char(5) fields, so if I simply use a string to store current lang code I’ll end in comparing “it” with “it ” because the database pads the string with space chars, due to the fact that the fields are fixed length strings. LangCode class is a very straightforward one:

public class LangCode : IEquatable<LangCode> {

internal LangCode() {

public LangCode(String langcode) {
mCode = langcode.Trim();

public String Code {
get { return mCode; }
set { mCode = value.Trim(); }
private String mCode;

#region Static lancode

public static LangCode It = new LangCode(“it”);
public static LangCode En = new LangCode(“en”);
public static LangCode De = new LangCode(“de”);


#region IEquatable<LangCode> Members

public bool Equals(LangCode other) {
return String.Compare(this.mCode, other.mCode, true) == 0;

public override bool Equals(object obj) {
if (obj == null) return false;
if (obj.GetType() != typeof(LangCode)) return false;
return Equals((LangCode) obj);

public override int GetHashCode() {
return mCode.GetHashCode();


I simply implement IEquatable interface and Equals() method, I also trim all lang code so I can use my legacy database that stores codes in fixed length string columns. To access Registry I simply used Windsor container and a static class:

readonly static IRegistry sRegistry = IoC.Resolve<IRegistry>();

static public LangCode CurrentLangCode {
get { return sRegistry.CurrentLangCode;}
set { sRegistry.CurrentLangCode = value; }

static public LangCode DefaultLangCode {
get { return sRegistry.DefaultLangCode; }
set { sRegistry.DefaultLangCode = value; }

This makes possible to use different concrete classes to implement the registry, for example for a web application I can store the current language in user session, while for simple windows application I simply set the language programmatically by code in member variables.

public class WinFormRegistry : IRegistry {

public LangCode CurrentLangCode {
get { return mCurrentLangCode; }
set { mCurrentLangCode = value; }
private static LangCode mCurrentLangCode = LangCode.En;

public LangCode DefaultLangCode {
get { return mDefaultLangCode; }
set { mDefaultLangCode = value; }
private static LangCode mDefaultLangCode = LangCode.En;

With castle Windsor I can specify in the app.config or web.config the right concrete class to use, this makes my Registry very flexible. Now the first point is satisfied, I have a registry that can be accessed from any class that needs to know current language or default languages. In the next post I’ll show you a possible scheme to handle a fully featured localized entity.


Localizable Entities with Nhibernate – Part 2
Localizable Entities with Nhibernate – Part 3

Caution with disposing session.Transaction

In nhibernate 1.2.0 beta versions a similar code path works well without problem

ISession session = SessionHelper.GetSession();
//do something
//Do something

But above code is not legal since a disposed transaction cannot be used anymore. Until version 1.2.0 beta 3 the Dispose method of the Transaction Object did not mark transaction as disposed, so it can be reused. Starting from NHibernate 1.2.0 GA the above code will throw a NullReferenceException. The solution is not to dispose Session.Transaction if you plan to restart a new transaction again.


Reassociated object has dirty collection

Today I Hitted this exception working with NHibernate, after consulting some posts on the net I discovered that this exception is raised when a detached object is reattached to a session with lock and the object has a one-to-many relation that was changed. The strange thing is that the same code works perfectly on a test web site and throw this error in production site. Moreover I’m sure that the whole object graph is unchanged and that the collections is not changed

After a couple of minutes I realized that a control store a detatched object in asp.net session and reattach with session.lock…the problem is that in production code session state is managed in sql server, so the object graph is serialized, then deserialized at the next request and reattached with session.lock(). It seems that the operations of serialization and deserialization make nhibernate think that the collection of objects is somewhat changed.


Nhibernate bug?

I replicated a bug in nhibernate. I have a simple mapping for a simple class 

<?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Ca1" assembly="Ca1" default-lazy="false" default-access="property"> <class name="Ca1.Cliente" table="Clienti" > <id name="Id" column="Id" type="int" unsaved-value="0"> <generator class="identity" /> </id> <property name="Nome" type="String" column="Nome" insert="true" update="true" /> <property name="Indirizzo" type="String" column="Indirizzo" not-null="false" insert="true" update="true" /> <property name="LocalizedData" type="string" update="false" formula='(SELECT ClientiLoc.loctext FROM ClientiLoc WHERE ClientiLoc.clieid = Id and ClientiLoc.lang = :CultureFilter.LangId)'/> </class> </hibernate-mapping>

The only particular issue is that LocalizedData Property is a formula and takes data from another table that contains localized data, the current locale is specified as a filter. The problem originates from the following simple code

using (NHibernate.ISession session = Helpers.CreateSession()) { using (NHibernate.ITransaction tran = session.BeginTransaction()) { IFilter flt = session.EnableFilter("CultureFilter"); flt.SetParameter("LangId", "it"); ICriteria criteria = session.CreateCriteria(typeof(Ca1.Cliente)); //criteria.Add(NHibernate.Expression.Expression.Like("Nome", "Gian%")); criteria.Add(NHibernate.Expression.Expression.Eq("LocalizedData", "loc_it")); criteria.Add(NHibernate.Expression.Expression.Like("Nome", "Gian%")); IList<Ca1.Cliente> result = criteria.List<Cliente>(); Console.WriteLine("Retrieved {0} objects", result.Count); } }

This code simply creates a criteria filter to select a cliente entity that has both the name like ‘Gian%’ and the localized italian version equal to “loc_it”. All works well and the query generated intercepted by the sql profiler is.

exec sp_executesql N'SELECT this_.Id as Id0_0_, this_.Nome as Nome0_0_, this_.Indirizzo as Indirizzo0_0_, (SELECT ClientiLoc.loctext FROM ClientiLoc WHERE ClientiLoc.clieid = this_.Id and ClientiLoc.lang = @p0) as formula0_0_ FROM Clienti this_ WHERE (SELECT ClientiLoc.loctext FROM ClientiLoc WHERE ClientiLoc.clieid = this_.Id and ClientiLoc.lang = @p1) = @p2 and this_.Nome like @p3', N'@p0 nvarchar(2),@p1 nvarchar(2),@p2 nvarchar(6),@p3 nvarchar(5)',@p0=N'it',@p1=N'it',@p2=N'loc_it',@p3=N'Gian%'

The sql is quite messy, the query is OK but has a strange duplicated parameter ‘it’ even if I put only criteria for localized query. The real problem originates if the two criteria are inverted in order.

criteria.Add(NHibernate.Expression.Expression.Like("Nome", "Gian%")); criteria.Add(NHibernate.Expression.Expression.Eq("LocalizedData", "loc_it"));

This simple change breaks the query:

exec sp_executesql N'SELECT this_.Id as Id0_0_, this_.Nome as Nome0_0_, this_.Indirizzo as Indirizzo0_0_, (SELECT ClientiLoc.loctext FROM ClientiLoc WHERE ClientiLoc.clieid = this_.Id and ClientiLoc.lang = @p0) as formula0_0_ FROM Clienti this_ WHERE this_.Nome like @p1 and (SELECT ClientiLoc.loctext FROM ClientiLoc WHERE ClientiLoc.clieid = this_.Id and ClientiLoc.lang = @p2) = @p3', N'@p0 nvarchar(2),@p1 nvarchar(2),@p2 nvarchar(5),@p3 nvarchar(6)',@p0=N'it',@p1=N'it',@p2=N'Gian%',@p3=N'loc_it'

Even is sql is quite messy you can notice that the parameters order is wrong. The second criteria ClientiLoc.lang = @p2 is wrong because @p2 parameter does not contain the ‘it’ value but the ‘Gian%’ value.

This problem happens every time I have a formula property that use a filter. To work correctly, every criteria on filter property must be the first criteria in the criteria collection.