2010-03-21 27 views
7

Estoy buscando mantener las preferencias del usuario en una colección de pares de valores de nombre, donde el valor puede ser un int, bool o cadena.Cómo mapear IDictionary <cadena, objeto> en Fluidez NHibernate?

Hay algunas maneras de pelar este gato, pero el método más conveniente que puedo pensar es algo como esto:

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

con su uso como:

user.Preferences["preference1"] = "some value"; 
user.Preferences["preference2"] = 10; 
user.Preferences["preference3"] = true; 

var pref = (int)user.Preferences["preference2"]; 

estoy no estoy seguro de cómo mapear esto en Fluent NHibernate, aunque sí creo que es posible.

En general, le asigne una cadena simple diccionario <, cadena > como:

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

Pero con un tipo de 'objeto', NHibernate no sabe cómo tratar con él. Me imagino que podría crearse un UserType personalizado que descompone un 'objeto' en una cadena que representa su Tipo y una cadena que representa el valor. Tendríamos una tabla que se ve algo así como esto:

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

y el mapeo de Hibernate se desea:

<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> 

No estoy seguro de cómo le gustaría asignar este Fluido en NHibernate.

Tal vez haya una mejor manera de hacerlo, o tal vez debería simplemente absorberlo y usar IDictionary < cadena, cadena >. ¿Algunas ideas?

+0

¿Encontró una solución? –

+0

Gracias, justo lo que estaba buscando – jolySoft

Respuesta

6

diría IDictionary<string,string> sería mucho más fácil. Sin embargo, aquí está el código

 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 
     }; 
     } 
    } 
} 
+0

Gracias por la ayuda amigo, detectar – jolySoft

+0

¿Qué es ImmutableUserType? No puedo encontrar una referencia en NHibernate o FNH. –

+0

@JeffDoolittle es mi propio basetype que implementa NH's IUseryType. lo publiqué aquí http://stackoverflow.com/a/7484139/671619 – Firo

Cuestiones relacionadas