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:
- 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.
- 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.
- 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?