Search code examples
c#asp.net-mvcnhibernatefluent-nhibernate

Fluent nHibernate dictionary customType


I have problem with CustomType in Fluent NHibernate. I have to save as Json a dictionary to my database. I created a customType for this that implements IUserType interface. There is no problem to save dictionary to database for first time, but when i try to update collection, nHibernate dont set a property as dirty and dont update it.

My Equals and GetHashCode methods

    public new bool Equals(object x, object y)
    {
        if (x == null && y == null)
            return true;

        if (x == null || y == null)
            return false;

        if (!(x is IDictionary<K, Z>) || !(y is IDictionary<K, Z>))
            return false;



        var dic1 = (x as IDictionary<K, Z>).OrderBy(z=> z.Key);
        var dic2 = (y as IDictionary<K, Z>).OrderBy(z => z.Key);

        return dic1.SequenceEqual(dic2);
    }

    public int GetHashCode(object x)
    {
        if (x == null)
            return 0;

        return x.GetHashCode();
    }

The objects passed to equals method are always the same (recently modified) two object. Anyone have a idea what i'm doing wrong ?

Rest of IUserType implementation code:

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        if (names.Length != 1)
            throw new InvalidOperationException("Only expecting one column...");

        var val = rs[names[0]] as string;

        if (val != null && !string.IsNullOrWhiteSpace(val))
        {
            return JsonConvert.DeserializeObject<T>(val, JSonSerializableTypeSerializer.Settings);
        }

        return null;
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var parameter = (DbParameter)cmd.Parameters[index];

        if (value == null)
        {
            parameter.Value = DBNull.Value;
        }
        else
        {
            parameter.Value = JsonConvert.SerializeObject(value, JSonSerializableTypeSerializer.Settings);
        }
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public object Assemble(object cached, object owner)
    {
        return cached;
    }

    public object Disassemble(object value)
    {
        return value;
    }

    public SqlType[] SqlTypes
    {
        get
        {
            return new SqlType[] { new StringClobSqlType() };
        }
    }

    public Type ReturnedType
    {
        get { return typeof(T); }
    }

    public bool IsMutable
    {
        get { return true; }
    }

Solution

  • Maybe I am wrong, but I guess you have returned false while implementing IUserType.IsMutable.

    Since your user type returns a Dictionary, which is a mutable type, and which you do indeed mutate, your user type must return true for its IsMutable property.