[Hibernate] Lazy loading en repositories

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb een vraag over lazy loading met (N)Hibernate.

Stel ik heb een systeem dat informatie over gerechten en ingredienten bevat. In hibernate heb ik dan een class Gerecht, met daarin een ISet Ingredienten.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Gerecht
{
   public Gerecht()
   {
   }

   public virtual Int64 ID
   { get en set code }

   public virtual string Naam
   { get en set code }

   public virtual ISet Ingredienten
   {
      get { return ingredienten }
      set { ingredienten = value }
   }
}


Dit is ook netjes gemapt in xml voor NHibernate, werkt allemaal prima.

Stel ik heb 't volgende scherm:

Ik heb een lijstje met gerechten in beeld, en als ik op een van de gerechten klik, dan krijg ik daaronder de ingredienten te zien. Ik maak gebruik van lazy loading, dus de ingredienten worden NIET opgehaald op het moment dat de lijst met gerechten wordt getoond.

Nu laat ik de repository de data ophalen middels NHibernate, hiervoor wordt netjes een session geopend en gesloten. Hieronder is een voorbeeldje te zien van hoe dat werkt:

C#:
1
2
3
4
5
ISession session = NHibernateHelper.GetCurrentSession();

ICriteria crit = session.CreateCriteria(typeof(Gerecht));
IList gerechten = crit.List();
NHibernateHelper.CloseSession();

(Dit is slechts voorbeeldcode)

De IList met gerechten wordt vervolgens door wat lagen heen teruggegeven aan de Web UI laag.

Op het moment dat ik nu een van de gerechten op het scherm selecteer, wil ik de ingredienten zien. Op dat moment heeft NHibernate weer een open sessie nodig. Nu dus mijn probleem:

Vraag
Moet ik nou ineens in de Web UI een NHibernate sessie gaan openen, zodat de bijbehorende detail info opgehaald kan worden? Eigenlijk wil ik helemaal niet in mijn UI met NHibernate sessies gaan lopen rommelen.
Ik kan echter ook niet de sessie open houden, omdat dan uiteindelijk het updaten niet goed gaat, want dan heeft NHibernate ineens twee open sessies (Illegal attempt to associate a collection with two open sessions )


Hoe doen jullie zoiets?

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:57
Als het met WebForms te maken heeft, dan zou ik er voor zorgen dat je een Sessie opent bij een request, en deze sessie opnieuw sluit als de request is afgelopen.
Dat kan je makkelijk doen, aangezien het hier toch over een paar milliseconden gaat.

Als het over WinForms gaat, is het natuurlijk een ander verhaal, want daar zit je geheid met long running sessions.

Over het feit dat je niet in je UI met NHibernate Sessions wilt gaan 'rommelen' ?
Waarom niet ?
Het is in jouw geval hoogstwaarschijnlijk zo dat het je UI is die de 'context' kent waarbinnen je domein object moet gebruikt worden. Maw: het is je UI die weet wanneer je een nieuwe sessie moet hebben, wanneer je een bestaande sessie kunt gebruiken, wanneer je een transactie moet starten of committen.
Waar ga je anders je session-management gaan doen ? Je domein model weet niets af van de 'context'; je repository (die eigenlijk imho deel uitmaakt van je domein model) ook niet.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
thanks voor je comments.
Ik zou er dus voor kunnen kiezen om een session vanuit de WebUI door de lagen heen door te geven aan de repository, die dus bijvoorbeeld twee parameters nodig heeft: een ID waarop gezocht moet worden, en de session die gebruikt moet worden. Zoiets bedoel je denk ik?
whoami schreef op vrijdag 14 november 2008 @ 15:18:
Over het feit dat je niet in je UI met NHibernate Sessions wilt gaan 'rommelen' ?
Waarom niet ?
Het is in jouw geval hoogstwaarschijnlijk zo dat het je UI is die de 'context' kent waarbinnen je domein object moet gebruikt worden. Maw: het is je UI die weet wanneer je een nieuwe sessie moet hebben, wanneer je een bestaande sessie kunt gebruiken, wanneer je een transactie moet starten of committen.
Waar ga je anders je session-management gaan doen ? Je domein model weet niets af van de 'context'; je repository (die eigenlijk imho deel uitmaakt van je domein model) ook niet.
Ik zat te denken om transacties te laten starten door de service laag. Als ik bijvoorbeeld naar een personeels system kijk, dan heb je mischien een ontslag service, die zorgt dat een ontslagdatum wordt geregistreerd, een e-mail naar de administratie wordt gestuurt om een ontslagbrief aan te maken en ga zo maar door.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:57
Verwijderd schreef op vrijdag 14 november 2008 @ 15:50:
thanks voor je comments.
Ik zou er dus voor kunnen kiezen om een session vanuit de WebUI door de lagen heen door te geven aan de repository, die dus bijvoorbeeld twee parameters nodig heeft: een ID waarop gezocht moet worden, en de session die gebruikt moet worden. Zoiets bedoel je denk ik?
Ongeveer.
Momenteel doe ik het zo (in een WinForms omgeving):
Bij het creeëren van een repository instance geef ik een ISession (eigenlijk een wrapper rond de session) mee aan de repository.
Mijn repository heeft bv een method 'GetPerson' die één argument heeft: het id van de op te halen persoon. De implementatie van deze method gebruikt dan de Session die ik (dmv de constructor) aan m'n repository heb doorgegeven om de persoon met het gegeven id op te halen.

In een Web omgeving zou je er evt voor kunnen kiezen dat je Repository zelf de huidige Sessie gaat gaan 'opzoeken'. Dan hoef je dus geen sessie mee te geven aan je repository.
Echter, de laag die de 'context' van je applicatie kent, blijft wel verantwoordelijk voor het 'starten' van de sessie.
Je kan op CodeProject eens zoeken naar een article van Billy McCafferty over NHibernate Best practices in ASP.NET.
Ik zat te denken om transacties te laten starten door de service laag. Als ik bijvoorbeeld naar een personeels system kijk, dan heb je mischien een ontslag service, die zorgt dat een ontslagdatum wordt geregistreerd, een e-mail naar de administratie wordt gestuurt om een ontslagbrief aan te maken en ga zo maar door.
Dan is het die service laag die de context kent, en dus verantwoordelijk is voor het starten / sluiten van sessies & transacties.

https://fgheysels.github.io/