Frage

Wie zeichnen Sie eine Klasse anderen Fällen derselben Klasse ab Wenn diese Beziehung Eigenschaften selbst hat?

Ich habe eine Klasse namens Person, die einer Tischperson zugeordnet ist

PersonID   PersonName    PersonAge 
----------------------------------
       1   Dave Dee             55
       2   Dozy                 52
       3   Beaky                45
       4   Mick                 55
       5   Tich                 58

Ich möchte eine viele zu viele Beziehung zwischen Person und Person mit einer Join-Tabelle namens Personaler:

 PersonPersonID  PersonID  RelatedPersonID RelationshipID 
 --------------------------------------------------------
              1         1                5              1
              2         3                4              2
              3         2                1              3

Ich möchte die folgenden Attribute in der Tabelle der Person Personen:

RelationshipID  RelationshipName
--------------------------------
             1  Colleague
             2  Manager
             3  Tutor

Diese Frage und das verlinkte Post von Billy McCafferty erklärt, dass die Beziehung zwischen Personen aufgrund der zusätzlichen Spalten in der Personalentabelle aus einer normalen Verbindung zu einem eigenen Rechtsanschluss befördert werden muss. Es erklärt jedoch nicht, was zu einem Selbstjoin ist. Der Unterschied besteht darin, dass, wenn ich nach allen verwandten Menschen frage Dave Dee (Id = 1), nicht nur sollte ich bekommen Tich (Id = 5), aber ich sollte auch bekommen Verschlafen (ID = 2) auch, weil Dave Dee auch in der verwandten Spalte ist.

Was meine Lösung bisher ist, ist es, zwei Eigenschaften in meiner Personklasse zu haben.

public virtual IList<PersonPerson> PersonPersonForward {get;set;}
public virtual IList<PersonPerson> PersonPersonBack {get;set;}

private List<PersonPerson> personPersonAll;
public virtual List<PersonPerson> PersonPersonAll 
{
   get
   {
       personPersonAll = new List<PersonPerson>(PersonPersonForward);
       personPersonAll.AddRange(PersonPersonBack);
       return personPersonAll;
   }
}

Und haben Folgendes in der HBM:

 <bag name="PersonPersonForward" table="PersonPerson" cascade="all">
      <key column="PersonID"/>
      <one-to-many class="PersonPerson" />
 </bag>

 <bag name="PersonPersonBack" table="PersonPerson" cascade="all">
      <key column="RelatedPersonID"/>
      <one-to-many class="PersonPerson" />
 </bag>

Dies scheint eine Kleinigkeit klobig und unelegant zu sein. Nhibernate hat normalerweise elegante Lösungen für die meisten alltäglichen Probleme. Ist die obige sinnvolle Art, dies zu tun, oder gibt es einen besseren Weg?

War es hilfreich?

Lösung

Ich denke, ich würde es auch so machen, aber ich denke, es ist ein bisschen „ungeschickt“, es so zu modellieren. Ich meine: Sie haben eine Sammlung von Personen, mit denen eine bestimmte Person verwandt ist, aber Sie haben auch eine „Rückverantwortung“.
Ist das wirklich notwendig? Ist es nicht eine Option, diese Rückfahrt zu entfernen, und geben Sie stattdessen eine Methode für das PersonRepository an, mit dem Sie alle Personen zurückgeben können, die eine Art Beziehung zu einer bestimmten Person haben?

Hmm, das kann vielleicht ein bisschen dunkel klingen, also hier ist ein Code (beachten Sie, dass ich aus Kürze die "virtuellen" Modifikatoren usw. ausgelassen habe (ich ziehe es auch vor, diese Modifikatoren nicht zu haben, also in 99 % der Fälle spezifiziere ich bei meinem Klassenkartier 'Lazy = false').

public class Person
{
    public int Id {get; set;}
    public string Name {get; set;}

    public IList<PersonPerson> _relatedPersons;

    public ReadOnlyCollection<PersonPerson> RelatedPersons
    {
        get
        {
           // The RelatedPersons property is mapped with NHibernate, but
           // using its backed field _relatedPersons (can be done using the 
           // access attrib in the HBM.
           // I prefer to expose the collection itself as a readonlycollection
           // to the client, so that RelatedPersons have to be added through
           // the AddRelatedPerson method (and removed via a RemoveRelatedPerson method).

           return new List<PersonPerson) (_relatedPersons).AsReadOnly();
        }
    }

    public void AddRelatedPerson( Person p, RelationType relatesAs )
    {
       ...
    }

}

Wie Sie sehen können, hat die Personklasse nur noch eine Sammlung übrig, dh eine Sammlung von Personen, die Beziehungen darstellen, die diese Person hat. Um die Personen zu erhalten, die Beziehungen zu einer bestimmten Person haben, können Sie eine bestimmte Methode auf Ihrem Personalrepository erstellen, die diese Personen zurückgibt, anstatt sie in einer Sammlung in der Personklasse zu haben. Ich denke, das wird auch die Leistung verbessern.

public class NHPersonRepository : IPersonRepository
{
    ...

    public IList<Person> FindPersonsThatHaveARelationShipWithPerson( Person p )
    {
        ICriteria crit = _session.CreateCriteria <Person>();

        crit.AddAlias ("RelatedPersons", "r");

        crit.Add (Expression.Eq ("r.RelatedWithPerson", p));

        return crit.List();

    }
}

Die 'Rückenreferenz' ist kein Mitglied der Personklasse; Es muss über das Repository zugegriffen werden. Dies ist auch das, was Eric Evans in seinem DDD - Buch sagt: In einigen Fällen ist es besser, eine spezielle Methode auf dem Repository zu haben, mit der Sie Zugriff auf verwandte Objekte ermöglichen können, anstatt sie (= die zugehörigen Objekte) zu haben, um sie herumzutragen mit dem Objekt selbst.

Ich habe den Code nicht getestet, ich habe ihn gerade hier eingegeben, deshalb habe ich auch nicht auf Syntaxfehler usw. gesucht, aber ich denke, er sollte ein wenig klarstellen, wie ich das sehen würde.

Andere Tipps

Es sieht für mich aus, als hätten Sie im Wesentlichen ein Modell von a gebaut gerichteter Graph, und die beiden Zuordnungen PersonPersonForward und PersonPersonBack darstellen ausgehende bzw. eingehende Kanten.

Diese Anweisungen wird durch die Semantik Ihrer Beziehungstypen verstärkt: während is-a-colleague-of ist höchstwahrscheinlich ein Symmetrische Beziehung, is-a-manager von und is-a-tutor von sind fast definitiv asymmetrisch.

Ich denke, in diesem Fall versucht das Datenmodell Ihnen zu sagen, dass die beiden Linkssammlungen im Kontext nicht dasselbe sind.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top