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!