How to map IDictionary <string, object> in Fluent NHibernate?

I want to save user preferences in a collection of name value pairs, where the value can be int, bool or string.

There are several ways to trick this cat, but the most convenient way that I can think of is something like this:

public class User { public virtual IDictionary<string, object> Preferences { get; set; } } 

using it as:

 user.Preferences["preference1"] = "some value"; user.Preferences["preference2"] = 10; user.Preferences["preference3"] = true; var pref = (int)user.Preferences["preference2"]; 

I am not sure how to match this in Fluent NHibernate, although I think it is possible.

Generally, you should map a simpler dictionary <string, string> as:

 HasMany(x => x.Preferences) .Table("Preferences") .AsMap("preferenceName") .Element("preferenceValue"); 

But with the type of "object", NHibernate does not know how to deal with it. I assume that a custom UserType can be created that breaks the "object" into a string representing its Type and a string representing its value. We will have a table that looks something like this:

 Table Preferences userId (int) preferenceName (varchar) preferenceValue (varchar) preferenceValueType (varchar) 

and the hibernation display will look like this:

 <map name="Preferences" table="Preferences"> <key column="userId"></key> <index column="preferenceName" type="String" /> <element type="ObjectAsStringUserType, Assembly"> <column name="preferenceValue" /> <column name="preferenceValueType"/> </element> </map> 

I'm not sure how you could match this in Fluent NHibernate.

Maybe there is a better way to do this, or maybe I just need to drag it in and use IDictionary <string, string>. Any ideas?

+7
dictionary mapping preferences fluent-nhibernate usertype
source share
1 answer

I would say that IDictionary<string,string> will be much simpler. However here is the code

  HasMany(u => u.Preferences) .Table("Preferences") .AsMap("preferenceName") .Element("preferenceType", e => e.Column("preferenceValue").Type<ObjAsStringUserType>()); class ObjAsStringUserType : ImmutableUserType { public override object NullSafeGet(IDataReader rs, string[] names, object owner) { var type = (string)NHibernateUtil.String.NullSafeGet(rs, names[0]); var value = (string)NHibernateUtil.String.NullSafeGet(rs, names[1]); switch (type) { case "boolean": return bool.Parse(value); ... default: return null; break; } } public override void NullSafeSet(IDbCommand cmd, object value, int index) { var type = value.GetType().Name; var valuestring = value.ToString(CultureInfo.InvariantCulture); NHibernateUtil.String.NullSafeSet(cmd, type, index); NHibernateUtil.String.NullSafeSet(cmd, valuestring, index + 1); } public override Type ReturnedType { get { return typeof(object); } } public override SqlType[] SqlTypes { get { return new [] { SqlTypeFactory.GetString(length: 255), // preferenceType SqlTypeFactory.GetString(length: 255), // preferenceValue }; } } } 
+6
source share

All Articles