7

Ich möchte Benutzerpräferenzen in einer Sammlung von Name-Wert-Paaren beibehalten, wobei der Wert ein Int, Bool oder String sein kann.Wie IDictionary <string, object> in Fluent NHibernate zugeordnet?

Es gibt ein paar Möglichkeiten, um diese Katze Haut, aber die bequemste Methode, die ich von ist denken kann, so etwas wie diese:

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

mit seiner Verwendung als:

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

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

Ich bin Ich bin mir nicht sicher, wie man das in Fluent NHibernate abbildet, obwohl ich denke, dass es möglich ist.

Im Allgemeinen würden Sie eine einfachere Wörterbuch < String Karte, string > als:

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

aber mit einer Art von ‚Objekt‘, ist NHibernate nicht wissen, wie sie damit umgehen. Ich stelle mir vor, dass ein benutzerdefinierter UserType erstellt werden könnte, der ein 'Objekt' in eine Zeichenkette zerlegt, die seinen Typ darstellt, und eine Zeichenkette, die den Wert darstellt. Wir würden eine Tabelle, die ein bisschen wie folgt aussieht:

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

und die Hibernate Mapping würde dies mag:

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

Ich bin nicht sicher, wie Sie dies in Fluent NHibernate Karte würde.

Vielleicht gibt es eine bessere Möglichkeit, dies zu tun, oder vielleicht sollte ich nur saugen und verwenden IDictionary < Zeichenfolge, Zeichenfolge >. Irgendwelche Ideen?

+0

Haben Sie eine Lösung gefunden? –

+0

Danke, genau das, was ich gesucht habe – jolySoft

Antwort

6

ich würde sagen, IDictionary<string,string> wäre viel einfacher. Aber hier ist der 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 
     }; 
     } 
    } 
} 
+0

Danke für die Hilfe fella, Spot auf – jolySoft

+0

Was ist ImmutableUserType? Ich kann keine Referenz in NHibernate oder FNH finden. –

+0

@ JeffDoolittle ist mein eigener Basistyp, der NHs IUseryType implementiert. Ich habe es hier http://stackoverflow.com/a/7484139/671619 veröffentlicht – Firo