2 Stimmen

Wie modelliert man eine Beziehung, die von NHibernate (oder Hibernate) nicht ohne weiteres unterstützt wird?

Ich habe eine Situation, in der die ideale Beziehung meines Erachtens die Vererbung von Wertobjekten wäre. Dies wird in NHibernate leider nicht unterstützt, so dass jede Lösung, die ich mir ausdenke, weniger als perfekt sein wird.

Sagen wir mal so:

  • "Item"-Entitäten haben einen "Standort", der in einem von mehreren verschiedenen Formaten vorliegen kann.
  • Diese Formate sind völlig unterschiedlich und haben keine überlappenden Felder.
  • Wir werden jeden Ort in dem Format behandeln, das in den Daten angegeben ist, und nicht versuchen, von einem Format in ein anderes zu konvertieren.
  • Jeder Gegenstand hat genau einen Standort.
  • "SpecialItem" ist ein Subtyp von Item, der jedoch insofern einzigartig ist, als er genau zwei Orte hat.
  • "Gruppe" Entitäten aggregieren Posten.
  • "LocationGroup" ist ein Subtyp von Group.
  • LocationGroup hat auch eine einzelne Location, die in jedem der oben beschriebenen Formate vorliegen kann.
  • Obwohl ich an Artikeln nach Gruppe interessiert bin, möchte ich auch alle Artikel mit demselben Standort finden können, unabhängig davon, in welcher Gruppe sie sich befinden.

Ich entschuldige mich für die Vielzahl der oben aufgeführten Bestimmungen, aber ich fürchte, dass eine weitere Vereinfachung die Schwierigkeiten der Situation nicht wirklich widerspiegeln würde. Hier ist, wie die oben genannten könnte diagrammed werden:

Mapping-Dilemma-Diagramm http://www.freeimagehosting.net/uploads/592ad48b1a.jpg

Die Analyse der obigen Ausführungen führt mich zu den folgenden Feststellungen:

  • Ich behandle Standorte polymorph und beziehe mich eher auf den Supertyp als auf den Subtyp.
  • Logischerweise sollten Standorte "Wertobjekte" und keine Entitäten sein, da es sinnlos ist, zwischen zwei Standortobjekten zu unterscheiden, die alle dieselben Werte haben. Daher sollte die Gleichheit zwischen Standorten auf Feldvergleichen und nicht auf Identifikatoren beruhen. Außerdem sollten Wertobjekte unveränderlich sein und gemeinsame Verweise sollten nicht zulässig sein.
  • Bei der Verwendung von NHibernate (oder Hibernate) würde man normalerweise Wertobjekte mit dem Schlüsselwort "component" abbilden, was dazu führen würde, dass die Felder der Klasse direkt in die Datenbanktabelle abgebildet werden, die die enthaltende Klasse darstellt. Mit anderen Worten: Es gäbe keine separate Tabelle "Standorte" in der Datenbank (und Standorte hätten daher keine Bezeichner).
  • NHibernate (oder Hibernate) unterstützen derzeit keine Vererbung für Wertobjekte.

Meine Wahlmöglichkeiten sind meiner Meinung nach folgende:

  1. Ignorieren Sie die Tatsache, dass Orte Wertobjekte sein sollten und bilden Sie sie als Entitäten ab. Dies würde die Probleme mit der Vererbungszuordnung lösen, da NHibernate die Vererbung von Entitäten unterstützt. Der Nachteil ist, dass ich dann mit Aliasing-Problemen umgehen muss. (Das heißt, wenn mehrere Objekte einen Verweis auf denselben Standort haben, würde eine Änderung der Werte für den Standort eines Objekts dazu führen, dass sich der Standort für andere Objekte ändert, die den Verweis auf denselben Standortdatensatz haben). Dies möchte ich nach Möglichkeit vermeiden. Ein weiterer Nachteil ist, dass Entitäten normalerweise anhand ihrer IDs verglichen werden. Dies würde bedeuten, dass zwei Location-Objekte als no gleich, auch wenn die Werte aller ihrer Felder gleich sind. Dies wäre ungültig und aus geschäftlicher Sicht inakzeptabel.
  2. Verflachen Sie Locations in eine einzige Klasse, so dass es keine Vererbungsbeziehungen mehr für Locations gibt. Dies würde es ermöglichen, Standorte als Wertobjekte zu behandeln, die durch die Verwendung des "Komponenten"-Mappings in NHibernate leicht gehandhabt werden könnten. Der Nachteil in diesem Fall wäre, dass das Domänenmodell schwächer, anfälliger und weniger wartbar wird.
  3. Führen Sie einige "kreative" Zuordnungen in den hbm-Dateien durch, um zu erzwingen, dass Standortfelder in die Tabellen der enthaltenen Entitäten zugeordnet werden, ohne das Schlüsselwort "Komponente" zu verwenden. Dieser Ansatz wird von Colin Jack beschrieben aquí . Meine Situation ist komplizierter als die von ihm beschriebene, da SpecialItem einen zweiten Standort hat und eine andere Entität, LocatedGroup, ebenfalls Standorte hat. Ich könnte es wahrscheinlich hinbekommen, aber die Zuordnungen wären nicht intuitiv und daher schwer zu verstehen und von anderen Entwicklern in Zukunft zu pflegen. Außerdem vermute ich, dass diese kniffligen Mappings mit Fluent NHibernate wahrscheinlich nicht möglich wären, so dass ich zumindest in dieser Situation die Vorteile dieses Tools nutzen würde.

Sicherlich sind andere da draußen in ähnliche Situationen geraten. Ich hoffe, dass jemand, der "das schon erlebt hat", etwas Weisheit weitergeben kann :-)

Die Frage ist also: Welcher Ansatz sollte in dieser Situation bevorzugt werden? Und warum? Gibt es eine bessere Option, die ich nicht in Betracht gezogen habe?

1voto

Péter Török Punkte 111735

Nur ein paar Beobachtungen/Fragen...

  • Wenn die verschiedenen Ortsformate keine sich überschneidenden Felder haben, welche Gemeinsamkeiten gibt es dann, die sie zu Kandidaten für eine Unterklassenhierarchie machen würden? Kann man eigentlich eine gemeinsame Schnittstelle für die Basisklasse definieren? Location ?
  • ist eine TypeALocation vergleichbar mit einem TypeBLocation ?
  • sind die beiden Orte in SpecialItem des gleichen Typs, oder können sie gemischt werden?
  • Kann ein Element seinen Standort zur Laufzeit in einen anderen Typ ändern?

Wie Sie oben schreiben, können Wertobjekte nicht polymorph sein. Basierend auf dem, was Sie beschreiben, sehe ich nicht, wie Sie Orte polymorph behandeln können.

更新情報 Wenn Sie keine gemeinsame Basisschnittstelle für Ihre Ortstypen definieren können, ist es sehr umständlich, sie polymorph zu behandeln, unabhängig davon, ob ORM vorhanden ist oder nicht . In Ihrem Beispiel unten mussten Sie, um Informationen über meinen tatsächlichen Wohnort zu erhalten, entweder eine Straßenadresse oder eine Längen-/Breitengradkoordinate eingeben. Polimorphismus ist genau dafür gedacht, solche Downcasts (und Umschaltungen von Typfeldern usw.) zu vermeiden!

Wenn man sich die von Ihnen beschriebenen Optionen ansieht und all dies berücksichtigt:

  1. Genau wie Sie mag ich es auch nicht (was kaum verwunderlich ist).
  2. Dies kann eine praktikable Option sein, wenn es nicht viele Standorttypen gibt und Sie einigermaßen sicher sein können, dass Sie alle jemals benötigten Typen implementiert haben. In diesem Fall wäre die Domänenklasse praktisch das Analogon zu einer C-Union, mit einem Typfeld. Es ist etwas umständlich zu benutzen, aber der polymorphe Versuch wäre IMHO noch umständlicher.
  3. Es ist auf jeden Fall eine interessante Idee, mit der ich wahrscheinlich irgendwann in einem Lieblingsprojekt experimentieren werde, aber ich bin mir nicht ganz sicher, ob ich solche Tricks in meinem Produktionscode haben möchte. Ich denke, man könnte es auch mit einem benutzerdefinierten Mapping-Typ machen, der Ihre Komponente einer bestimmten Unterklasse zuordnet. Aber dann sind wir wieder bei dem Versuch, diese inkompatiblen Typen in eine Typenhierarchie einzupassen... der einzige gute Grund, diesen Weg auszuprobieren, ist, wenn es viele Standorttypen gibt und/oder neue Typen in der Zukunft auftauchen könnten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X