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; }
}
IUserType.Equals
implementation always get the same object reference forx
andy
? And what are your returning forIsMutable
? – FrédéricReplace
implementation would causes issues if you work with detached entities. It should copyoriginal
totarget
for supportingMerge
. YourAssemble
andDisassemble
implementations will cause issues if you use second level cache. They should at least yield deep copies, but maybe would it be better to cache (disassemble) the JSon serialization instead and de-serialized it on assemble. SeeIUserType
comments. – Frédéric