2009-04-06 3 views
2

Gibt es eine Möglichkeit, NHibernate dazu zu bringen, dass ich mehrere ChildObjects in der ChildObjectTable speichern kann, sie aber auf verschiedene ParentObjects zurückverweise? Oder muss ich eine separate ChildObject-Klasse/Tabelle für jeden ParentObject-Typ erstellen?NHibernate: Wie ordne ich mehrere Kinder eines gemeinsamen Typs mehrerer Eltern in einer einzigen Tabelle?

ich diese gekocht habe auf die folgenden unten, ich versuche, diese Objekte abzubilden:

public class ParentObjectA 
{ 
    public virtual Int64 Id { get; private set; } 

    public virtual IDictionary<int, ChildObject> Children { get; private set; } 
} 

public class ParentObjectB 
{ 
    public virtual Int64 Id { get; private set; } 

    public virtual IDictionary<int, ChildObject> Children { get; private set; } 
} 

public class ChildObject 
{ 
    public virtual Int64 Id { get; private set; } 
} 

in der folgenden Tabelle Struktur:

ParentObjectTableA 
    Id bigint 

ParentObjectTableB 
    Id bigint 

ChildObjectTable 
    Id bigint 
    ParentId bigint 
    ParentQualifier varchar(50) 
+0

Es ist mir gerade in den Sinn gekommen, dass ich das wahrscheinlich mit einem Crossstable lösen könnte, was mich mit NHibernate in ein Viel-zu-viele-Gebiet bringen würde. Ich würde das lieber nicht machen müssen, wenn es einfacher wäre, es in diese Struktur zu integrieren. –

Antwort

0

Die folgenden Karten scheinen aus der Objektperspektive zu funktionieren. Ich bin nicht übermäßig scharf auf die Idee, Kreuztabellen zu verwenden, aber ich denke, das könnte sauberer sein als der Versuch, mit Vererbung umzugehen. Ich werde mir diese Option auch ansehen und werde meine Ergebnisse hier veröffentlichen, um sie zu vervollständigen. Kommentare willkommen.

Mapping von ParentObjectA

<map name="Children" table="ParentAxChildObject"> 
    <key column="ParentId" /> 
    <index column="ChildObjectNumber" type="Int32" /> 
    <many-to-many class="ChildObject" /> 
</map> 

Mapping von ParentObjectB

<map name="Children" table="ParentBxChildObject"> 
    <key column="ParentId" /> 
    <index column="ChildObjectNumber" type="Int32" /> 
    <many-to-many class="ChildObject" /> 
</map> 

Diese erzeugen die folgenden Kreuztabellen:

ParentAxChildObject 
    [ParentId] [bigint] NOT NULL, 
    [elt] [bigint] NOT NULL, 
    [ChildObjectNumber] [int] NOT NULL, 

ParentBxChildObject 
    [ParentId] [bigint] NOT NULL, 
    [elt] [bigint] NOT NULL, 
    [ChildObjectNumber] [int] NOT NULL, 
+0

Es sollte beachtet werden, dass das Tabellenattribut in der Map nicht in der NHibernate-Dokumentation dokumentiert ist. Ich vermutete es, nachdem ich festgestellt hatte, dass es versuchte, standardmäßig eine Kreuztabelle aus dem 'name'-Attribut zu erstellen. –

+0

Das schafft eine konsolidierte 'Children' Kollektion? Ordentlich. Sehr interessante Annäherung, die ich vorher nicht gesehen habe. –

1

Vielleicht könnten Sie eine abstrakte Basis erstellen Klasse für Ihre Elternklassen? Auf diese Weise könnte ein bestimmtes untergeordnetes Objekt auf den abstrakten Typ für sein übergeordnetes Objekt verweisen.

Zum Beispiel können Sie eine Klasse namens ParentBase haben, die ParentClassA und ParentClassB erweitern. Ihr untergeordnetes Objekt hat eine Referenz zurück zu ParentBase.

Dies ist alles möglich mit NHibernate verschiedenen inheritance models.

+0

Das stimmt. Ich verwende diese Technik eigentlich woanders, aber ich habe nicht einmal daran gedacht, sie hier anzuwenden, weil ich versucht habe, eine gemeinsame Basisklasse zu vermeiden. Wird das auch mit Schnittstellen funktionieren? –

+0

Ich bin unsicher, wie NHibernate mit Schnittstellen in einem Mapping-Szenario umgeht. –

0

ich die Vererbungs Version habe arbeiten auch mit einem Schnittstelle als Basis und wollte es hier zur Fertigstellung posten.

public interface IParent 
{ 
    IList<Child> children { get; set; } 
    void AddChild(Child child); 
    Int64 Id { get; set; } 
    Child GetChild(); 
} 

public class Parent : IParent 
{ 
    public virtual IList<Child> children { get; set; } 

    public Parent() 
    { 
     children = new List<Child>(); 
    } 

    public virtual void AddChild(Child child) 
    { 
     children.Add(new Child()); 
    } 

    public virtual Int64 Id { get; set; } 

    public virtual Child GetChild() 
    { 
     return children.First(); 
    } 
} 

public class Parent2 : IParent 
{ 
    public virtual IList<Child> children { get; set; } 

    public Parent2() 
    { 
     children = new List<Child>(); 
    } 

    public virtual void AddChild(Child child) 
    { 
     children.Add(new Child()); 
    } 

    public virtual Int64 Id { get; set; } 

    public virtual Child GetChild() 
    { 
     return children.First(); 
    } 
} 


public class Child 
{ 
    public virtual Int64 Id { get; private set; } 
} 

Diese werden mit der folgenden abgebildet:

<class name="IParent" table="IParents"> 
    <id name="Id" unsaved-value="0"> 
     <column name="Id" sql-type="bigint" /> 
     <generator class="hilo" /> 
    </id> 

    <bag name="children" cascade="all"> 
     <key column="ParentId" /> 
     <one-to-many class="Child" /> 
    </bag> 

    <joined-subclass name="Parent" table="Parents" > 
     <key column="ParentId" /> 
    </joined-subclass> 

    <joined-subclass name="Parent2" table="Parents2" > 
     <key column="ParentId" /> 
    </joined-subclass> 
</class> 

<class name="Child" table="Children"> 
    <id name="Id" unsaved-value="0"> 
     <column name="Id" sql-type="bigint" /> 
     <generator class="hilo" /> 
    </id> 
</class> 

Dies wiederum schafft die folgenden Tabellen:

IParents 
    Id bigint 

Parents 
    ParentId bigint 

Parents2 
    ParentId bigint 

Children 
    Id bigint 
    ParentId bigint 

Der große ‚Gotcha‘ ist hier bewusst zu sein, dass das Kind Objekt bezieht sich nur direkt auf die ID in der IParents-Tabelle. Und jede Instanz des Objekts Parent oder Parent2 ist abhängig von dem abgeleiteten Objekttyp, mit dem Sie gerade arbeiten, an einen verbundenen Aufruf zwischen IParents und entweder Parents oder Parents2 gebunden.

Ich habe dies noch nicht mit einer Klasse mit mehreren Schnittstellen getestet, aber ich muss das auch testen.

Was ich am Vererbungsmodell nicht mag ist, dass ich eine gemeinsame Schnittstelle/Basisklasse haben muss. Ich bin mir nicht sicher, warum ich das ablehnend finde, es wirkt einfach klobig.

Ich denke, ich werde für jetzt mit der Crossstable-Methode rollen und später wieder besuchen, wenn ich muss.

Verwandte Themen