NHibernate: Fetch Join + EntityCache

In unserer Test-basierten Entwicklung hat sich die Verwendung von Setup-Klassen für unsere Entities etabliert. Unsere Tests sehen folgendem sehr ähnlich:

[Test]
public void FetchJoinTest()
{
    var cat = _categorySetup.GetPersisted();
    var pitch = _pitchSetup.GetPersisted(p => { p.Categories.Add(cat); return p; });
    var reserv1 = _reservationSetup.GetPersisted(r =>
                                                     {
                                                         r.Pitch = pitch;
                                                         r.DateFrom = new DateTime(2009, 10, 31);
                                                         r.DateTo = new DateTime(2009, 11, 13);
                                                         return r;
                                                     });
 
    pitch = _pitchService.GetById(pitch.Id);
    Assert.That(pitch.Reservations.Count, EqualTo(2));
}
 

Leider funktioniert der Test so nicht - er schmeißt eine AssertionException, da pitch.Reservations keine Elemente enthält.

Warum nicht???

Nach langem hin und her, bin ich mir endlich sicher, es verstanden zu haben: es liegt an NHibernate's Entity-Cache! Da das Pitch-Objekt ja zum Zeitpunkt der Abfrage

 
    pitch = _pitchService.GetById(pitch.Id);
 

noch in der aktuellen Session geladen ist (was NHibernate meines Wissens nach anhand der ID feststellt), wird kein neues Objekt vom Typ Pitch instanziiert, sondern das schon existierende, pitch, zurückgegeben. Dieses enthielt aber noch keine Reservierungen zum Zeitpunkt der Persistierung - und so, wie es aussieht, werden diese auch nicht nachträglich geladen (für ein Objekt, das schon in der Session lebt).

Die Lösung ist jetzt gar nicht mehr so schwer: wir schmeißen das vorhandene Objekt einfach weg! Dafür gibt es Session.Evict():

[Test]
public void FetchJoinTest()
{
    var cat = _categorySetup.GetPersisted();
    var pitch = _pitchSetup.GetPersisted(p => { p.Categories.Add(cat); return p; });
    var reserv1 = _reservationSetup.GetPersisted(r =>
                                                     {
                                                         r.Pitch = pitch;
                                                         r.DateFrom = new DateTime(2009, 10, 31);
                                                         r.DateTo = new DateTime(2009, 11, 13);
                                                         return r;
                                                     });
 
    _nHibernateHelper.Session.Flush();
    _nHibernateHelper.Session.Evict(pitch);
 
    pitch = _pitchService.GetById(pitch.Id);
    Assert.That(pitch.Reservations.Count, EqualTo(2));
}

Jetzt läuft der Test mit Erfolg durch. Happy Coding!

Wenn ihnen der Artikel gefallen hat oder er für sie hilfreich war, bitten "kicken" sie ihn.
kick it on dotnet-kicks.de

Kommentare

Oktober 16. 2009 12:08

Robert

Der ReseverationService sollte/könnte die Reservations des Pitches mitsetzten. Dann müsste der Pitch nicht evicted werrden und ein Roundtrip wäre nicht nötig.

Robert

Kommentar schreiben


(Zeigt dein Gravatar icon)

  Country flag

biuquote
  • Kommentar
  • Live Vorschau
Loading



Über speak-friend

Wir Stefan, Oliver, Anton und Robert, sind die Entwickler von speak-friend.

Hier schreiben wir über unsere Coding-Abenteuer.

Letzten Kommentare