| 

.NET C# Java Javascript Exception

3
Hallo zusammen,

wir haben ein etwas anderes Datenmodell, welches die Verwendung von NHibernate nicht unbedingt vereinfacht. Jedes Objekt (z.B. eine Person) hat einen Eintrag in einer Tabelle. Hier steht die eindeutige Id und eine Bezeichnung. In einer anderen Tabelle stehen alle Attributwerte, die zu diesem Objekt gehören. Hier ein Beispiel:

Objekttabelle:
obj_id  | bezeichnung
1 | mustermann


Attributetabelle:
obj_id | att_id | value
1 | 0815 | max
1 | 4711 | 01.01.1970


So würde beispielsweise gespeichert, das es eine Person mit dem Nachnamen mustermann gibt, die mit Vornamen max heißt und am 1.1.1970 geboren ist. 0815 ist hierbei der Attributschlüssel für den Vornamen. Wenn kein Geburtsdatum zu einer Person hinterlegt ist, gibt es auch keine Eintrag in der Attributetabelle. (Jede Kombination aus obj_id/att_id darf nur 0..1 mal vorkommen).

Jetzt zu meiner Frage: Hat jemand eine Idee, wie ich soetwas mit (Fluent) NHibernate mappen kann?
Ich glaube am einfachsten ist es mit einem (outer) join. Da fehlt mir aber dann für jedes Attribut noch ein zusätzlicher Wert, nämlich der Schlüssel des Attributes. Bisher bekomme ich immer mehrere Werte zurück und somit nicht das gewünschte Ergebnis.

Join("Attributetabelle", Sub(mm)
mm.KeyColumn("obj_id")
mm.Optional()
mm.Map(Function(x) x.Vorname, "value")
End Sub)


Für das Speichern/Löschen könnte ich ja dann entsprechende SQL Statements hinterlegen.

Oder hat jemand eine Bessere Idee wie ich das Problem löschen kann??

Vielen Dank!

JenneB

PS: Bitte keine Kommentare zum Datenmodell bzw. einer Empfehlung dieses zu ändern. Das Modell ist nicht von mir und ändern kann ich es auch nicht.
News:
06.10.2011
JenneB 206 4
Du müßtest ja irgendwo ein Mapping von Attributschlüsseln auf Attributnamen haben. In welcher Form liegt das vor? Eine weitere DB-Tabelle? Eine externe Doku?
Matthias Hlawatsch 06.10.2011
Ne, da gibt es auch wieder ein Tabelle für. Da steht beschrieben, welche att_id welche Beschreibung im Frontend hat und zu zu welcher Art Objekt (der Klasse) es gehört.
JenneB 06.10.2011
1 Antwort
2
Das Datenmodell ist so ungewöhnlich nicht, mit sowas hatte ich auch schon mal zu tun (allerdings war damals kein OR-Mapper im Spiel).

Wenn Du das Design der Entities beeinflussen kannst, so wäre ein pragmatischer (und aus performance-Sicht möglicherweise vorteilhafter) Ansatz, alle zu einem Objekt gehörenden Werte aus der Attributetabelle in ein Dictionary zu laden und nur dieses Dictionary zu persistieren. Die Properties Deiner Entities wären dann alle transient und würden jeweils mit dem passenden Schlüssel auf das Dictionary zugreifen, um ihre Werte zu schreiben oder zu lesen.

Update
Nach Deinen Kommentaren sieht es so aus, als handelte es sich um ein Datenbankschema, das als "Generic Schema" oder "Generic Table Structure" bezeichnet wird. Jedenfalls habe ich mit diesen Bezeichnungen die meisten Treffer bei Google gefunden. Es ist unglaublich flexibel, aber zu einem sehr hohen Preis: langsam, skaliert schlecht, Abfragen lassen sich eher umständlich formulieren. Vor allem aber ist es als relationales Datenbankmodell eigentlich ein entarteter Fall: die Relationen stecken nicht mehr in der Schemastruktur, sondern rein in den Daten. Insofern halte ich die Frage für berechtigt, ob ein OR-Mapper wie NHibernate hier überhaupt das richtige Tool ist. Außer "selber schreiben" habe ich aber auch keine Alternative anzubieten. Vielleicht meldet sich ja noch jemand hier.
Ich kenne von Hibernate eher die Java-Variante, mit NHibernate habe ich noch nichts gemacht. Von Fluent NHibernate habe ich aufgeschnappt, dass es nicht alle Möglichkeiten abdeckt, die sich mit der XML-basierten Mapping-Definition darstellen lassen. Von daher wäre mein Rat, zu überlegen, ob Du mit der XML-Variante weiter kommst. Eventuell kannst Du dort bei den Joins noch die zusätzliche Bedingung auf den Attributschlüssel angeben, die Du ja brauchst, um den Wert für ein einzelnes Attribut zu bekommen - entweder in "Mapping-Sprache" oder mit viel custom SQL.
Alternativ könntest Du auch überlegen, ob Du im Code eine Schicht einziehst, die die Tabellenstruktur annähernd 1:1 repräsentiert und sich damit sehr leicht mappen läßt. Darauf aufsetzend könntest Du dann die Daten zu den gewünschten Objekten zusammensetzen. Wichtig wäre in diesem Zusammenhang auch zu überlegen, inwieweit sich die Flexibilität des Datenmodells im .NET-Code widerspiegeln soll. Welchen Sinn hat es, in der DB ohne Schema-Änderung einer Entität ein neues Attribut hinzufügen zu können, wenn es (wegen des Mappings auf eine .NET-Klasse mit einer Eigenschaft pro Attribut) einer Änderung am Programmcode bedarf, um es verwenden zu können?
06.10.2011
Matthias Hlawatsch 13,2k 4 9
Dann müsste ich eine Liste meiner Person haben, in der ich dann über die att_id als Schlüssel auf die Attribute zugreife !? Das fänd ich ein bisschen lästig, weil ich ja dann in jeder Property für den Einzelwert (z.B. Vorname) prüfen muss ob der Wert schon existiert, die Entity ggf. neu initialisieren oder löschen muss. Gibt es da keine Möglichkeit direkt auf die Properties zu mappen?
JenneB 06.10.2011
Der Zugriff aufs Dictionary wäre ziemlich stereotyp - dafür könntest Du Dir eine Helfermethode basteln, die sich um "nicht vorhanden" und dergleichen kümmert. Pro Property bleibt dann nicht viel mehr als ein Aufruf der Helfermethode mit dem Schlüssel als Parameter.
Lästiger als ein aufwendiges Mapping zu pflegen wäre das m.E. nicht.
Den Vorteil sehe ich darin, dass Du nur einen einzigen Join brauchst statt einen Join für jedes einzelne Attribut, um eine Objektinstanz zu laden.
Matthias Hlawatsch 06.10.2011
Ok, für die einfachen Datentypen bekomme ich das wohl mit einer Hilfsmethode hin. Aber wie würde das dann laufen, wenn in value wiederum ein Verweis auf ein anderes Objekt steht? Beim mapping der einzelnen Properties müsste mann ja nur entweder den Wert mappen oder references verwenden. Aber hier komm ich ja nicht wirklich weiter. Vor allem beim LazyLoading.
JenneB 06.10.2011
Du willst sagen, in Attributetabelle.value stehen z.T. Fremdschlüssel in die Objektetabelle?
Matthias Hlawatsch 06.10.2011
ja (leider)
JenneB 06.10.2011
bzw. der wert steht sowohl in der spalte value als auch in einer weiteren spalte in der Attributetabelle. Aber welcher Typ von Objekt dahinter steckt, kann ich nicht wirklich sinnvoll herausfinden.
JenneB 06.10.2011
Oh je, das ist wirklich ein schwieriger Fall. Für's Mapping geht das in Richtung worst case, finde ich. Ich habe meine Antwort um einige Überlegungen erweitert. Eine richtige Lösung kann ich Dir leider nicht anbieten.
Matthias Hlawatsch 07.10.2011
Ok. Vielen Dank erstmal für deine ausführlichen Beschreibungen und deine Hilfe. Ich werde mal sehen was ich machen kann. Es muss ja nicht unbedingt NHibernate sein, Hauptsache ist, dass ich nicht ständig die SQL-Statements und die Property-Mappings neu schreiben muss. Denn das kostet mich viel Zeit und ist fehleranfällig.
JenneB 07.10.2011

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH