Frage

Ich bin derzeit mit NHibernate als meine Datenzugriffsschicht, mit Fluent NHibernate die Mapping-Dateien für mich zu erstellen. Ich habe zwei Klassen, TripItem und TripItemAttributeValue, die eine many-to-many-Beziehung zwischen ihnen haben.

Die Zuordnung ist wie folgt:

public class TripItemMap : ClassMap<TripItem2>
{
    public TripItemMap()
    {
        WithTable("TripItemsInt");
        NotLazyLoaded();

        Id(x => x.ID).GeneratedBy.Identity().WithUnsavedValue(0);
        Map(x => x.CreateDate, "CreatedOn").CanNotBeNull();
        Map(x => x.ModifyDate, "LastModified").CanNotBeNull();

        /* snip */

        HasManyToMany<TripItemAttributeValue>(x => x.Attributes).AsBag()
            .WithTableName("TripItems_TripItemAttributeValues_Link")
            .WithParentKeyColumn("TripItemId")
            .WithChildKeyColumn("TripItemAttributeValueId")
            .LazyLoad();
    }
}

public class TripItemAttributeValueMap : ClassMap<TripItemAttributeValue>
{
    public TripItemAttributeValueMap()
    {
        WithTable("TripItemAttributeValues");

        Id(x => x.Id).GeneratedBy.Identity();
        Map(x => x.Name).CanNotBeNull();

        HasManyToMany<TripItem2>(x => x.TripItems).AsBag()
            .WithTableName("TripItems_TripItemAttributeValues_Link")
            .WithParentKeyColumn("TripItemAttributeValueId")
            .WithChildKeyColumn("TripItemId")
            .LazyLoad();
    }
}

An einem gewissen Punkt in meiner Anwendung ich vorhandene Attribute aus der Datenbank holen, fügen Sie sie tripItem.Attributes, speichern Sie die tripItem Objekt. Am Ende erhält die TripItems_TripItemAttributeValues_Link nie neue Datensätze in den Beziehungen resultierenden nicht beibehalten werden.

Wenn es hilft, das sind die Mapping-Dateien, die durch Fluent NHibernate für diese Klassen:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="true" assembly="ETP.Core" namespace="ETP.Core.Domain">
  <class name="TripItem2" table="TripItemsInt" xmlns="urn:nhibernate-mapping-2.2" lazy="false">
    <id name="ID" column="ID" type="Int32" unsaved-value="0">
      <generator class="identity" />
    </id>
    <property name="CreateDate" column="CreatedOn" type="DateTime" not-null="true">
      <column name="CreatedOn" />
    </property>
    <property name="ModifyDate" column="LastModified" type="DateTime" not-null="true">
      <column name="LastModified" />
    </property>
    <bag name="Attributes" lazy="true" table="TripItems_TripItemAttributeValues_Link">
      <key column="TripItemId" />
      <many-to-many column="TripItemAttributeValueId" class="ETP.Core.Domain.TripItemAttributeValue, ETP.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </bag>
  </class>
</hibernate-mapping>

und

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="true" assembly="ETP.Core" namespace="ETP.Core.Domain">
  <class name="TripItemAttributeValue" table="TripItemAttributeValues" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" column="Id" type="Int32">
      <generator class="identity" />
    </id>
    <property name="Name" column="Name" length="100" type="String" not-null="true">
      <column name="Name" />
    </property>
    <bag name="TripItems" lazy="true" table="TripItems_TripItemAttributeValues_Link">
      <key column="TripItemAttributeValueId" />
      <many-to-many column="TripItemId" class="ETP.Core.Domain.TripItem2, ETP.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
    </bag>
  </class>
</hibernate-mapping>

Was bin ich falsch hier?

War es hilfreich?

Lösung

@efdee

Ich habe das gleiche Problem und verbrachte fast zwei Tage auf diesem. Ich hatte eine viele zu viele Beziehungen und die Verknüpfungstabelle auch nicht aktualisiert wurde. Ich bin neu in NHibernate, einfach alles, was es so zu lernen, ich versuche, mit einem Körnchen Salz sagen.

Nun, es stellte sich heraus, dass es nicht Fluent NHibernate, noch die Zuordnung, aber mich nicht zu verstehen, wie NHibernate mit many-to-many funktioniert. In einem Viele-zu-viele-Beziehung, wenn Sammlungen auf beiden Entitäten nicht belegt sind, wird NHibernate keine Daten an die Verknüpfungstabelle bestehen bleiben.

Lassen Sie uns sagen, ich habe diese Entitäten in einem many-to-many-Beziehung:


partial class Contact
{
   public string ContactName {get; set;}
   public IList Locations {get; set;}

}

partial class Location
{
   public string LocationName {get; set;}
   public string LocationAddress {get;set;}
   public IList Contacts {get;set;}
}

, wenn ich an einen Ort zu Contact.Locations hinzufügen, muss ich sicherstellen, dass der Kontakt innerhalb location.Contacts auch vorhanden ist.

so einen Ort hinzufügen ich diese Methode in meiner Kontaktklasse haben.


public void AddLocation(Location location)
        {
            if (!location.Contacts.Contains(this))
            {
                location.Contacts.Add(this);
            }
            Locations.Add(location);
        }

Das scheint mein Problem gelöst zu haben, aber wie ich schon sagte, ich bin nur NHibernate aufzunehmen und es zu lernen, kann es eine bessere Art und Weise. Wenn jemand eine bessere Lösung hat, bitte posten.

Dies ist der Beitrag, den ich zeigte beiden Sammlungen zu überprüfen: http://www.coderanch.com/t/217138/Object-Relational-Mapping/link-table-of-ManyToMany-annotation

Andere Tipps

Rufen session.flush () oder Transaktion verwendet werden.

David Kemp hat es richtig. Sie eine Kaskade zu Ihrer Tasche hinzufügen möchten

Ich habe immer von Hand bearbeitet (und von Hand erstellt) die Mapping-Dateien, so dass meine natürliche Neigung ist es dort zu setzen. Sie können das tun, wie folgt:

<bag name="TripItems" lazy="true" table="TripItems_TripItemAttributeValues_Link" cascade="all">
  <key column="TripItemAttributeValueId" />
  <many-to-many column="TripItemId" class="ETP.Core.Domain.TripItem2, ETP.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>

Ich habe festgestellt, dass meine Klassen ‚rein‘ zu halten und hielt alles mit nHibernate in der .hbm.xml Datei meiner Lösung zu tun sauberer hält. Auf diese Weise, wenn es eine neue ORM-Software ist das ich verwenden möchte, habe ich die Mapping-Dateien nur ersetzen, und schreiben Sie nicht über die Klassen. Wir nutzen unsere Unit-Tests, die Klassen zu testen und geben Testbarkeit der xml, obwohl ich irgendwie tun wie Fluent NHibernate Methoden.

Ich habe genau das gleiche Problem, aber ich habe den NHibernate.JetDriver im Einsatz. Ich habe versucht, die empfohlene Antwort ohne Erfolg verwenden. Weiß jemand, ob die NHibernate.JetDriver eine Einschränkung in Bezug auf many-to-many hat?

Hier sind meine hbm Dateien, falls jemand bei der Überprüfung der sie für einen Moment zu interessieren passiert:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Ace.Docs.Core.Domain" assembly="Ace.Docs.Core">
<class name="Ace.Docs.Core.Domain.Address, Ace.Docs.Core" table="Addresses" lazy="true">
    <id name="Id" column="ID">
        <generator class="identity" />
    </id>
    <property name="Address1" column="Address1" />
    <property name="Address2" column="Address2" />
    <property name="City" column="City" />
    <property name="EmailAddress" column="EmailAddress" />
    <property name="Phone1" column="Phone1" />
    <property name="Phone2" column="Phone2" />
    <property name="PostalCode" column="PostalCode" />
    <property name="StateOrProvince" column="StateOrProvince" />
    <many-to-one name="AddressTypeMember" column="AddressTypeID" class="AddressType" />
    <bag name="HasPersonalInfo" table="Link_PersonalInfo_Addresses" lazy="true" cascade="save-update" inverse="true" >
        <key column="AddressID"></key>
        <many-to-many column="PersonalInfoID" class="PersonalInfo" />
    </bag>
</class>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Ace.Docs.Core.Domain" assembly="Ace.Docs.Core">
<class name="Ace.Docs.Core.Domain.PersonalInfo, Ace.Docs.Core" table="PersonalInfo" lazy="true">
    <id name="Id" column="ID">
        <generator class="identity" />
    </id>
    <property name="Prefix" column="Prefix" />
    <property name="FirstName" column="FirstName" />
    <property name="MiddleName" column="MiddleName" />
    <property name="LastName" column="LastName" />
    <property name="SIN" column="SIN" />
    <property name="Birthdate" column="Birthdate" />
    <property name="Note" column="Notes" />
    <bag name="HasAddress" table="Link_PersonalInfo_Addresses" lazy="true" cascade="save-update" inverse="true" >
        <key column="PersonalInfoID"></key>
        <many-to-many column="AddressID" class="Address" />
    </bag>
</class>

Ich habe es und ich hoffe, dass dies jemand anderes da draußen hilft. Das Problem ist, dass ich auf beiden Taschen inverse = ‚true‘ hatte. Wenn Sie den Ausschnitt unten lesen Sie werden bemerken, dass es nur auf einer der Taschen zu wahren inverse Satz sein muss:

Beachten Sie die Verwendung von inversen = "true". Wieder einmal diese Einstellung teilt NHibernate Änderungen die Kategorien Sammlung gemacht zu ignorieren und das andere Ende des Vereins nutzen - die Elemente Sammlung -. Als die Darstellung, die mit der Datenbank synchronisiert werden sollte

Ich fürchte Cascade.All () ist nicht wirklich die Lösung für mein Problem - es ist eines der Dinge war ich versuchte. Das Problem ist nicht, dass die Elemente der Sammlung hinzugefügt werden nicht gespeichert - sie sind bereits in der Datenbank zum Zeitpunkt des zur Sammlung hinzugefügt sind zu werden. Es ist nur so, dass die Einträge in der Verknüpfungstabelle werden nicht erstellt werden. Außerdem denke ich, Cascade.All () auch untergeordnete Elemente gelöscht werden verursachen würde, was in meinem Szenario nicht erwünschtes Verhalten ist. Ich habe mit Cascade.SaveUpdate versucht (), aber wie ich darauf hingewiesen habe, dies löst etwas, das meint nicht wirklich Problem ist: -)

Allerdings, um sicherzustellen, ich werde diese Lösung versuchen und lassen Sie wissen, das Ergebnis.

Wie für die Klassen rein zu halten, das ist 100% der Fall mit Fluent NHibernate. Die Klassenzuordnungen erstellen Sie sind C # -Code-Dateien, die neben Ihren Entitätsklassen gehen, ziemlich viel wie .hbm.xml Dateien würde.

ich kämpfen mit diesem als auch, und kam von einem ganz anderen Grund für meine Probleme. In meinem Beispiel hatte, wenn ich ein Objekt ohne many-to-many-Beziehungen konnte ich saveOrUpdate nur nennen, und alles wäre gut. Aber wenn ich irgendwelche many-to-many-Beziehungen hatte, musste ich sicherstellen, dass mein saveOrUpdate Anruf war innerhalb eines Begintrans und CommitTransaction. Ich bin sehr neu für fließend Nhibernate, so entschuldige mich, wenn dies offensichtlich ist. Aber es war mir nicht.

scroll top