nhibernatenhibernate-3

nhibernate, 0 in foreign key column


I got a legacy database where the value of 0 was used in FK columns to indicate that no relation have been specified.

This is not something that I can change in a trivial way. Is it possible to tell NHibernate to treat 0 as null in specified columns?

Edit

I know about not-found, but I just want to ignore those with 0.


Solution

  • This solution worked great for us: http://nhibernate.info/blog/2011/01/28/how-to-use-0-instead-of-null-for-foreign-keys.html

    In short:

    Add the following class:

    public class NullableTuplizer : PocoEntityTuplizer
    {
        public NullableTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity)
            : base(entityMetamodel, mappedEntity)
        {
        }
    
        public override object[] GetPropertyValuesToInsert(
            object entity, IDictionary mergeMap, ISessionImplementor session)
        {
            object[] values = base.GetPropertyValuesToInsert(entity, mergeMap, session);
            //dirty hack 1
            for (int i = 0; i < values.Length; i++)
            {
                if (values[i ] == null && typeof (IEntity).IsAssignableFrom(getters[i ].ReturnType))
                {
                    values[i ] = ProxyFactory.GetProxy(0, null);
                }
            }
            return values;
        }
    
        public override object[] GetPropertyValues(object entity)
        {
            object[] values = base.GetPropertyValues(entity);
            //dirty hack 2
            for (int i = 0; i < values.Length; i++)
            {
                if (values[i ] == null && typeof (IEntity).IsAssignableFrom(getters[i ].ReturnType))
                {
                    values[i ] = ProxyFactory.GetProxy(0, null);
                }
            }
            return values;
        }
    
    
        public override void SetPropertyValues(object entity, object[] values)
        {
            //dirty hack 3.
            for (int i = 0; i < values.Length; i++)
            {
                if (typeof (IEntity).IsAssignableFrom(getters[i ].ReturnType)
                    && ((IEntity) values[i ]).Id == 0)
                {
                    values[i ] = null;
                }
            }
            base.SetPropertyValues(entity, values);
        }
    }
    

    Then register it for every relevant mapping:

    foreach (var persistentClass in configuration.ClassMappings)
    {
        persistentClass.AddTuplizer(EntityMode.Poco, typeof(NullableTuplizer).AssemblyQualifiedName);
    }