NHibernate: many-to-many-Beziehung versagt Kind zu retten Objekte zuerst (entweder: „kann nicht null einfügen“ oder: „transient Objekt“)

StackOverflow https://stackoverflow.com/questions/1819851

Frage

Ich habe eine Sendung Klasse, die eine FreightDateTime Klasse aggregiert. Zur gleichen Zeit wird die FreightDateTime Klasse auch von der GoodsItem Klasse zusammengefasst. Auf die gleiche Weise wird FreightDateTime mit einer Reihe von anderen Klassen zugeordnet, die ich jetzt außen vor.

Um eine Datenbanktabelle FreightDateTime mit ConsignmentId Fremdschlüsseln zu vermeiden, ein GoodsItemId Fremdschlüssel usw. habe ich beschlossen, dass die Verein many-to-many sein sollte. Auf diese Weise NHibernate würde eine Zuordnungstabelle für jede Beziehung statt (ConsigmentFreightDateTimes, GoodsItemFreightDateTimes) erzeugen, was mehr Sinn macht.

Also, in der Zuordnungsdatei, sucht der Verein zum Beispiel wie folgt aus:

<bag name="DateTimes" table="FreightDateTimes" lazy="false" cascade="all">
  <key column="ConsignmentId"/>
  <many-to-many class="Logistics.FreightDateTime, Logistics" column="DateTimeId" />
</bag>

Einstellung Kaskade auf "alle" ergibt:

System.Data.SqlClient.SqlException: Cannot insert the value NULL into column 'DateTimeId', table 'LogiGate.dbo.FreightDateTimes'; column does not allow nulls. INSERT fails. 

Einstellung Kaskade auf "none" ergibt:

NHibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Logistics.FreightDateTime

In beiden Fällen bedeutet dies, dass NHibernate versucht, die Sendung Instanz zu speichern, obwohl das Kind FreightDateTime Fällen nicht gespeichert wurden. Im ersten Fall ist der Fremdschlüssel noch ‚null‘, die somit nicht in der resultierenden Tabelle eingefügt werden können, und im zweiten Fall ist NHibernate bewusst, dass die Instanz noch nicht gespeichert wurde, und wirft somit die Ausnahme.

Die Frage ist also, wie ich NHibernate bekommen kann alle untergeordneten Instanzen speichern zunächst ohne es ausdrücklich zu sagen, dies zu tun. Ich habe krümmen, dass die Zulassung nulls auf Spalte DateTimeId würde den Trick tun, aber ich denke, dass weder wünschenswert noch möglich ist.

War es hilfreich?

Lösung

Versuchen Sie, den Verband auf der anderen Seite abzubilden, sondern auch die inverse = „true“ -Attribut auf dieser Seite. So erstellen Sie in der FreightDateTime Zuordnungsdatei eine Tasche den Verein so viele-zu-viele mit der Sendung kartieren.

Außerdem habe ich eine ähnliche Frage hier beantwortet: Was ist der richtige Weg, viele-zu-viele-Beziehungen in NHibernate zu definieren Löschungen zu ermöglichen, aber doppelten Datensätze zu vermeiden

Lesen Sie die Frage und meine Antwort vielleicht hilft Ihnen verstehen, was mit Ihrem many-to-many Verein los ist und Sie vielleicht einen Hinweis für die Lösung geben. Die endgültige Empfehlung ist eine Art letzter Ausweg.

Die Antwort auf die obige Frage ist nur eine Vorstellung davon zu geben, was durch eine andere Person die andere Frage geht.

Eine Lösung wäre, um explizit die Zuordnungstabelle zuordnen. Wenn Ihre Tabellen sind: Person, Hinweis und die Zuordnungstabelle (X-Tisch) ist PersonNote Ihre Zuordnungen so aussehen sollte:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="..."
                   namespace="...">

  <class name="Person" table="Person" lazy="true">

    <id name="PersonId">
      <generator class="native" />
    </id>
    <property name="FirstName" />
    .....
    <bag name="PersonNotes" generic="true" inverse="true" lazy="true" cascade="none">
        <key column="PersonId"/>
        <one-to-many class="PersonNote"/>
    </bag>

    <bag name="Notes" table="PersonNote" cascade="save-update">
      <key column="PersonId"></key>
      <many-to-many class="Note" column="NoteId"></many-to-many>
    </bag>

  </class>

</hibernate-mapping>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="..."
                   namespace="...">

  <class name="Note" table="Note" lazy="true">

    <id name="NoteId" unsaved-value="0">
      <generator class="native" />
    </id>
    <property name="Title" />
    ....
    <bag name="PersonNotes" inverse="true" lazy="true" cascade="all-delete-orphan">
        <key column="NoteId"/>
        <one-to-many class="PersonNote"/>
    </bag>

    <bag name="People" table="PersonNote" inverse="true" cascade="save-update" generic="true">
      <key column="NoteId"></key>
      <many-to-many class="Person" column="PersonId"></many-to-many>
    </bag>

  </class>

</hibernate-mapping>

Wie es ist darüber Sie das erlaubt folgendes:

  1. Löschen einer Person und nur den Eintrag in der Zuordnungstabelle löschen, ohne dass die Hinweise löschen
  2. Geben Sie eine Anmerkung löschen und nur den Eintrag in der Zuordnungstabelle löschen, ohne dass die Person Entitäten löschen
  3. Speichern mit Cascades nur von der Person Seite durch die Person.Notes Sammlung bevölkern und Speichern der Person.
  4. Da die inversen = true ist notwendig, in der Note.People es nicht eine Möglichkeit ist save von dieser Seite zu tun kaskadieren. Durch die Note.People Sammlung bevölkert und dann den Hinweis Objekt Speichern Sie einen Einsatz auf den Hinweis Tisch und einen Einsatz auf die Tabelle Person, aber keinen Einsatz an die Zuordnungstabelle erhalten. Ich denke, das ist, wie NHibernate funktioniert und ich habe noch keinen Weg darum herum gefunden.
  5. Sie können kaskadiert speichern Einträge in der Zuordnungstabelle nur explizit durch neue Elemente in der PersonNotes Sammlung der Note Einheit hinzufügen.

Alle oben mit Unit-Tests getestet. Sie müssen die PersonNote Klassenzuordnungsdatei und Klasse für die oben zu arbeiten.

erstellen

Wenn Sie eine andere Klasse Noten zu haben, läßt Organisation sagen, dann Anzeige, die Sie nur eine andere Zuordnungstabelle zu Ihrem Schema namens OrgnanisationNote und Sie tun das gleiche, wie oben für die Organisation Zuordnungsdatei und die Hinweis Zuordnungsdatei.

Ich muß noch einmal sagen, dass dies die letzte Möglichkeit für jedermann sein sollte, die vollständige Kontrolle über seine / ihre many-to-many Verbände haben will.

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