NHibernate: Fetch Join + EntityCache

by Oliver 16. October 2009 13:28

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!

Comments are closed

About Oliver

shades-of-orange.com code blog logo I build web applications using ASP.NET and have a passion for javascript. Enjoy MVC 4 and Orchard CMS, and I do TDD whenever I can. I like clean code. Love to spend time with my wife and our children. My profile on Stack Exchange, a network of free, community-driven Q&A sites

About Anton

shades-of-orange.com code blog logo I'm a software developer at teamaton. I code in C# and work with MVC, Orchard, SpecFlow, Coypu and NHibernate. I enjoy beach volleyball, board games and Coke.