2009-07-21 16 views
4

Kann mir jemand dieses kleine Geheimnis erklären, wie NHibernate mit Verbundelementen umgeht?Warum löscht NHibernate dann Composite-Elemente bei Auswahl einfügen?

Ich habe Klassen, die so aussehen;

public class Blog 
{ 
    public virtual int Id 
    { 
     get; 
     private set; 
    } 

    public virtual ISet<Comment> Comments 
    { 
     get; 
     set; 
    } 
} 

public class Comment 
{ 
    public virtual string CommentText 
    { 
     get; 
     set; 
    } 

    public virtual DateTime Date 
    { 
     get; 
     set; 
    } 
} 

und Zuordnungen wie diese;

<class name="Blog" table="blog"> 
    <id name="Id" column="id" unsaved-value="0"> 
     <generator class="hilo"/> 
    </id> 

    <set name="Comments" table="blog_comments"> 
     <key column="blog_id" /> 
     <composite-element class="Comment"> 
     <property name="CommentText" column="comment" not-null="true" /> 
     <property name="Date" column="date" not-null="true" /> 
     </composite-element> 
    </set> 

    </class> 

Allerdings, wenn ich eine Auswahl wie diese durchführen;


using (ITransaction transaction = session.BeginTransaction()) 
{ 
    Blog blog = session.CreateCriteria(typeof(Blog)) 
        .SetFetchMode("Comments", FetchMode.Eager) 
        .Add(Expression.IdEq(2345))    
        .UniqueResult(); 

    transaction.Commit(); 
} 

NHibernate gibt eine select mit einem Join den Blog mit den Beiträgen zu bekommen, aber löscht dann alle Kommentare und fügt dann die Kommentare! Warum macht es das? Wenn ich keine Transaktion verwende, führt sie NUR die Auswahl und nicht die DELETE- und INSERT-Funktion aus, wie ich es erwarten würde. Was vermisse ich? Ich verwende NHibernate 2.0

Antwort

5

Ich glaube, Sie brauchen Equals() und GetHashCode() auf Kommentar zu überschreiben. NHibernate hat keine ID für die Entitätsgleichheit, sodass Sie definieren müssen, was eine Kommentarentität einem anderen Kommentar gleich macht.

könnte falsch sein :)


bearbeiten

Von: http://www.nhforge.org/doc/nh/en/index.html#components-incollections (7,2)

Hinweis: Wenn Sie ein ISet von Verbundelementen zu definieren, ist es sehr wichtig zu implementieren Equals() und GetHashCode() korrekt.

und ein Beispiel für die Umsetzung Equals/GetHashCode

http://www.nhforge.org/doc/nh/en/index.html#persistent-classes-equalshashcode (4,3)

+0

Danke, ich hatte diese in meiner Vollversion implementiert, aber muss etwas falsch in der Überschreibung für GetHashCode gemacht haben, das Beispiel, das Sie zur Verfügung gestellt hat, funktioniert wie ein Charme. Danke nochmal. – Gareth

-1

Meine Frage wäre, warum Sie begehen, wenn Sie nur eine Auswahl treffen müssen? Ich glaube, der Grund dafür, dass alle Kommentare gelöscht werden, ist, dass das Blog-Objekt und die zugehörigen Kommentare in der Sitzung zwischengespeichert werden, die zum Erstellen der Transaktion verwendet wird, wenn Sie commit für die Transaktion aufrufen. Wenn Sie das Commit aufrufen, bewirken Sie, dass alle Objekte in der Sitzung gespeichert werden, die das Sichern in der Datenbank verursachen. Mir ist nicht klar, warum es die Kommentare löscht, aber es ist korrekt, die Objekte zu speichern.

ich auch stumbled upon this today:

NHibernate löscht meine ganze Sammlung und es stattdessen der Aktualisierung der Tabelle neu zu erstellen.

Dies passiert im Allgemeinen, wenn NHibernate kann nicht herausfinden, welche Elemente in der Sammlung geändert. Häufige Ursachen sind:

  • eine persistente Sammlung komplett mit einer neuen Kollektion Instanz ersetzt
  • vorbei NHibernate ein manuell konstruiertes Objekt und ruft aktualisieren darauf.
  • Serialisierung/Deserialisierung einer persistenten Sammlung verursacht offenbar auch dieses Problem.
  • Aktualisieren von a mit inverse = "false" - in diesem Fall kann NHibernate SQL nicht erstellen, um ein einzelnes Sammlungselement zu aktualisieren.

So, das Problem zu vermeiden:

  • die gleiche Sammlung Instanz übergeben, die Sie von NHibernate bekamen zurück, um es (nicht unbedingt in der gleichen Sitzung),
  • versuchen stattdessen eine andere Sammlung mit von (oder), oder
  • versuchen Sie mit inverse = "True" -Attribut für.
+0

Ich dachte, dass die Entitäten aktualisieren begehen würde nur die verändert wurden - wie keine haben, warum wäre es etwas zu aktualisieren versuchen? Ich lese auch diese Seite http://ayende.com/Blog/archive/2008/12/28/nh-prof-alerts-use-of-implicit-transactions-is-discouraged.aspx – Gareth

+0

Ich stimme zu, dass Sie nicht sollten verwende implizite Transaktionen, mir war nur unklar, warum Sie die Transaktion durchführen würden, wenn nichts geändert wurde. Auf jeden Fall mag ich diese Frage und die Antwort war sehr informativ! – lomaxx

+0

-1 weil Sie immer explizite Transaktionen haben sollten, und ohne commits erhalten Sie Warnungen. – BradLaney

Verwandte Themen