Was ist die richtige Methode zum Definieren von Viele-zu-Viele-Beziehungen in NHibernate, um Löschungen zuzulassen, aber doppelte Datensätze zu vermeiden?

8

Ich habe schon seit ein paar Tagen mit einem NHibernate-Setup gekämpft und kann einfach nicht herausfinden, wie ich mein Mapping richtig einstellen soll, damit es so funktioniert, wie ich es mir vorstelle.

Es gibt ein bisschen Code, den ich durchlaufen muss, bevor ich zu den Problemen komme, daher entschuldige ich mich im Voraus für das zusätzliche Lesen.

Das Setup ist im Moment ziemlich einfach, mit nur diesen Tabellen:

Kategorie
KategorieId
Name

Artikel
Artikel-ID
Name

ItemCategory
Artikel-ID
Kategorieindikation

Ein Element kann in vielen Kategorien vorkommen und jede Kategorie kann viele Elemente enthalten (einfache Viele-zu-Viele-Beziehung).

Ich habe meine Zuordnung wie folgt festgelegt:

%Vor%

Meine Methoden zum Hinzufügen von Elementen zur Objektliste in der Kategorie- und Kategorieliste in Objekt legen beide Seiten der Beziehung fest.

In Artikel :

%Vor%

In Kategorie :

%Vor%

Nun, das ist aus dem Weg, die Probleme, die ich habe, sind:

  1. Wenn ich 'inverse="true"' aus dem Category.Items-Mapping entferne, erhalte ich doppelte Einträge in der Lookup-ItemCategory-Tabelle.

  2. Wenn 'inverse="true"' verwendet wird, erhalte ich einen Fehler, wenn ich versuche, eine Kategorie zu löschen, da NHibernate den übereinstimmenden Datensatz nicht aus der Nachschlagetabelle löscht, also aufgrund der Fremdschlüsseleinschränkung fehlschlägt.

  3. Wenn ich cascade="all" auf die Taschen setze, kann ich ohne Fehler löschen, aber das Löschen einer Kategorie löscht auch alle Elemente in dieser Kategorie.

Gibt es ein grundlegendes Problem mit der Art und Weise, wie ich mein Mapping eingerichtet habe, damit das Viele-zu-Viele-Mapping wie erwartet funktionieren kann?

Mit "so wie Sie es erwarten würden" meine ich, dass Löschvorgänge nichts mehr löschen als das gelöschte Element und die entsprechenden Nachschlagewerte (wobei das Element am anderen Ende der Beziehung unberührt bleibt) und Aktualisierungen für jede Sammlung aktualisiert die Nachschlagetabelle mit korrekten und nicht doppelten Werten.

Alle Vorschläge würden sehr geschätzt.

    
Kevin Wilson 08.11.2009, 01:38
quelle

2 Antworten

10

Was Sie tun müssen, damit Ihre Zuordnungen so funktionieren, wie Sie es erwarten würden, ist das Verschieben des inverse="true" von der Category.Items Sammlung in die Item.Categories Sammlung. Auf diese Weise werden Sie NHibernate verstehen lassen, welche die besitzende Seite der Assoziation ist, und das wäre die "Category" -Seite.

Wenn Sie das tun, wird durch Löschen eines Category-Objekts der übereinstimmende Datensatz so aus der Nachschlagetabelle gelöscht, wie Sie möchten, da dies die besitzende Seite der Assoziation ist.

Um KEINE Elemente zu löschen, die einem Category-Objekt zugewiesen sind, das gelöscht werden soll, müssen Sie die Kaskadenattribute wie folgt lassen: cascade="save-update" .

cascade="all" löscht die Elemente, die dem gelöschten Category-Objekt zugeordnet sind.

Ein Nebeneffekt wäre jedoch, dass das Löschen der Entität auf der Seite, auf der die inverse = tru existiert, eine Fremdschlüsselverletzung auslöst, da der Eintrag in der Zuordnungstabelle nicht gelöscht wird.

Eine Lösung, bei der Ihre Zuordnungen genau so funktionieren, wie Sie möchten, dass sie funktionieren (anhand der Beschreibung, die Sie in Ihrer Frage angegeben haben), besteht darin, die Zuordnungstabelle explizit zuzuordnen. Ihre Abbildungen sollten so aussehen:

%Vor%

Wie oben, können Sie Folgendes tun:

  1. Löschen Sie eine Kategorie und löschen Sie nur den Eintrag in der Zuordnungstabelle, ohne eines der Elemente zu löschen
  2. Löschen Sie einen Eintrag und löschen Sie nur den Eintrag in der Zuordnungstabelle, ohne einen der Kategorien
  3. zu löschen
  4. Speichern Sie mit Cascades nur von der Kategorieseite, indem Sie die Category.Items-Auflistung auffüllen und die Kategorie speichern.
  5. Da die inverse = true in den Item.Categories notwendig ist, gibt es keine Möglichkeit Cascading von dieser Seite zu speichern. Wenn Sie die Item.Categories-Auflistung auffüllen und dann das Item-Objekt speichern, erhalten Sie eine Einfügung in die Item-Tabelle und eine Einfügung in die Kategorie-Tabelle, aber kein Einfügen in die Zuordnungstabelle. Ich denke, so funktioniert NHibernate und ich habe noch keinen Weg gefunden.

Alle oben genannten werden mit Komponententests getestet. Sie müssen die Klassenzuordnungsdatei und Klasse für die ItemCategory-Klasse erstellen, damit das oben genannte funktioniert.

    
tolism7 08.11.2009, 21:29
quelle
1

Halten Sie die Sammlungen synchron? Hibernate erwartet von Ihnen, glaube ich, einen korrekten Objektgraph; Wenn Sie einen Eintrag aus Item.Categories löschen, müssen Sie den gleichen Eintrag aus Category.Items löschen, damit die beiden Sammlungen synchronisiert sind.

    
RMorrisey 08.11.2009 02:08
quelle