2009-09-01 5 views
5

Ich versuche herauszufinden, wie IDictionary-Eigenschaft in fließenden 1.0 RTM zugeordnet werden.Fließender Code zum Zuordnen eines IDictionary <SomeEntity, int>?

Aus meinem Verständnis übersetzt sich dies in eine ternäre Assoziation.

Beispiel:

class Bar 
{ 
    public IDictionary<SomeEntity, int> Foo {get; set;} 
} 

Bar.hbm.xml würde dann enthalten:

<map name="Foo" table="BarFooTable"> 
    <key column="..."/> 
    <index-many-to-many class="SomeEntity" column="SomeEntity_Id"/> 
    <element column="Value" type="int"/> 
</map> 

Was habe ich in fließend nhibernate schreiben diese Zuordnung xml zu produzieren?

Der Punkt von Interesse ist hier, dass der Schlüssel ein Entitätstyp ist, während der Wert ein Werttyp ist. (edit: Zumindest scheint sich das von den verschiedenen anderen Beispielen und Fragen zu unterscheiden, die auf stackoverflow- oder google-Gruppen herumfliegen, die Wert-Wert oder Schlüssel-Schlüssel sind)

Nach vielen Experimenten kann ich ein Mapping für ein IDictionary<SomeEntity,SomeEntity> (reine Entitätstypen):

HasManyToMany(x => x.Foo) 
     .AsMap("Key") 
     .AsTernaryAssociation("Key2", "Value") 
     ; 

ich auch eine Zuordnung für ein IDictionary<int,int> (reine Werttypen) produzieren können:

HasMany(x => x.Foo) 
    .AsMap<int>("Key") 
    .Element("Value") 
    ; 

ich kann sogar eine gewisse Art und Weise erhalten eine Zuordnung für einzur Herstellung von, obwohl keine, die NHibernate akzeptiert.

Aber ich kann nicht herausfinden, wie man ein Mapping für eine IDictionary<SomeValue, int> erstellen, was ich will. Kann mir jemand Tipps geben?

+0

gecrosspostet zu http://groups.google.com/group/fluent-nhibernate/browse_thread/thread/b1b335ff5f9a6a40 – fostandy

Antwort

1

ich in das gleiche Problem lief, und wasn‘ t glücklich mit dem Mischen von fließenden und hbm Mappings. Sie können meinen Fix here sehen.

0

Es scheint, wir haben das gleiche Problem:

How to map this in Fluent.NHibernate

ich nur verwendet hbm.xml (das von Fluent.Nhibernate in meinem Projekt generiert wurde) ich es ein wenig oufcourse modifiziert. Wenn Sie setzen

.Mappings(m => 
    {            
     m.FluentMappings.AddFromAssemblyOf<DomainClass>() 
         .ExportTo("Path"); 
     m.HbmMappings.AddFromAssemblyOf<DomainClass>(); 
    }) 

und wenn Sie beide ClassMap haben und hbm.xml die hbm.xml sollte die ClassMap außer Kraft setzen, so dass Sie in Ordnung, bis sein es behoben ist.

Ich brauche auch natürliche Nummer für meine Klasse, und es wird auch nicht mit Fluent.Nhibernate unterstützt, so hatte ich keine andere Wahl, als hbm.xml zu verwenden

+0

Ja, das ist zur Zeit so, wie ich bin Dinge auch tun. Leider habe ich eine ziemlich schwere Klasse, die, obwohl sie viele Eigenschaften hat, die fließend abgebildet werden können, auch ein IDictionary hat. Meine bisherige "Lösung" war es, die Funktionalität in separate Klassen zu unterteilen (eine wird flüssig zugeordnet, eine über rohe hbm.xml) und eine Eins-zu-Eins-Zuordnung verwenden, aber aus Performance-Gründen ist es jetzt wünschenswert, die Join/extra auswählen, die von diesem auftritt. (Siehe http://groups.google.com/group/fluent-nhibernate/browse_frm/thread/b5fe376e257436e9/35d9cf5cef4303d0) – fostandy

2
HasMany(x => x.Foo) 
    .KeyColumn("BarId") 
    .Element("IntValue") 
    .AsMap<SomeEntity>("SomeEntityId") 
    .AsTernaryAssociation("SomeEntityId"); 
+0

Hatte das gleiche Problem, basierend auf Ihrer Lösung endete ich mit 'HasManyToMany (x => x. collection) \t \t \t \t .ParentKeyColumn ("ParentId") \t \t \t \t .ChildKeyColumn ("childID") \t \t \t \t .AsMap ("childID"). Element ("Value", p => p .Column ("Wert"). Typ ()) \t \t \t \t .AsTernaryAssociation ("childID", "Value") \t \t \t \t \t \t \t \t .Tabelle ("Relationstable"); ' –

0

In Anbetracht dieser (vereinfacht) Klassen:

class LetterTemplate 
{ 
    IDictionary<State, FieldAccessOptionality> StateAccess {get; protected set;} 
} 

class State 
{ 
} 

enum FieldAccessOptionality 
{ 
} 

Das ist für mich gearbeitet.

(Ja, ich weiß, der Wert ist eine Enum, aber das Prinzip ist das gleiche wie ein int).

HasManyToMany(x => x.StateAccess) 
    .ParentKeyColumn("`letter_template`") 
    .ChildKeyColumn("`state`") 
    .AsMap<State>("`state`") 
    .Element("`access`", 
     p => 
     p.Type<IntEnumType<FieldAccessOptionality>>()) 
    .AsTernaryAssociation("`state`", "`access`") 
    .Table("`letter_template_state_access`"); 

Notiere die IntEnumType <> Klasse, die für NHibernate von Enum in einen int umwandelt. Wenn Sie ein int anstelle einer enum zuordnen würden, könnten Sie einfach den standardmäßigen NHibernate Int32Type IUserType verwenden. Die vollständige Liste für diese Klasse ist wie folgt:

public class IntEnumType<T> : IUserType where T : struct 
{ 
    public object Assemble(object cached, object owner) 
    { 
    return cached; 
    } 

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

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

    public new bool Equals(object a, object b) 
    { 
    return Object.Equals(a, b); 
    } 

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

    public bool IsMutable 
    { 
    get { return false; } 
    } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
    object result = NHibernateUtil.Int32.NullSafeGet(rs, names); 
    if (result == null) 
    { 
     return null; 
    } 
    else 
    { 
     Type typ = Enum.GetUnderlyingType(typeof(T)); 
     result = Convert.ChangeType(result, typ); 
     return Enum.ToObject(typeof(T), result); 
    } 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
    if (value == null) 
     ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value; 
    else 
     ((IDataParameter)cmd.Parameters[index]).Value = Convert.ChangeType(value, typeof(int)); 
    } 

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

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

    public SqlType[] SqlTypes 
    { 
    get 
    { 
     SqlType type = new SqlType(DbType.Int32); 
     return new SqlType[] { type }; 
    } 
    } 

} 
Verwandte Themen