[C#.NET] NHibernate strategie

Pagina: 1
Acties:
  • 146 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben bezig een ontwerp te maken voor een nieuwe applicatie.
De bedoeling is om de classes op te slaan dmv hibernate in de database.
Dit lukt allemaal, maar ben nog heel nieuw in het gebruik van hibernate.

Ik heb een aantal classes die worden gemapt in de database. Bij de classes
heb ik Factory's gemaakt. Bijvoorbeeld een class Gebruiker met een GebruikersFactory
waarin bijvoorbeeld de methode GetGebruikers een lijst met alle gebruikers terug geeft.

Nu is mijn vraag: Is het de bedoeling dat de applicatie bij het opstarten alle gebruikers
uit de database haalt en in het programma laat in een property en dat ik dan bij GetGebruikers
die property return, of moet ik bij elke methode in de factory een query via hibernate uitvoeren?
In mijn vorige projectgroep waren de meningen hierover verdeelt.

Nu nog iets over de session. Nu maak ik bij elke connectie naar de database (bv. in GebruikersFactory.GetGebruikers()) een session aan, doe ik een trancactie en sluit ik de session weer. Is dit ook de bedoeling, of moet ik 1 sessie aanmaken die ik elke keer aanroep?

Acties:
  • 0 Henk 'm!

  • Ansur
  • Registratie: Januari 2004
  • Laatst online: 24-06 12:02
Verwijderd schreef op maandag 14 januari 2008 @ 12:39:
Nu is mijn vraag: Is het de bedoeling dat de applicatie bij het opstarten alle gebruikers
uit de database haalt en in het programma laat in een property en dat ik dan bij GetGebruikers
die property return, of moet ik bij elke methode in de factory een query via hibernate uitvoeren?
In mijn vorige projectgroep waren de meningen hierover verdeelt.
Dit hangt van de applicatie af lijkt me. Als je bv. nooit meer dan 50 gebruikers zal moeten beheren kan je inderdaad opteren om ze allemaal in te laden. Zit je 5000+ gebruikers en je laadt deze allemaal ineens in, zal je wel eens memory problemen kunnen krijgen.
In het tweede geval lijkt paging me aangewezen.

Sessies... is het een desktopapplicatie? Ik denk dat je in dat geval maar 1 sessie object nodig zal hebben.

Oh en btw.als die GetGebruikers() je data niet modified, moet je geen transactie starten. Enkel nodig bij update/delete statements.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:30
Verwijderd schreef op maandag 14 januari 2008 @ 12:39:
Nu is mijn vraag: Is het de bedoeling dat de applicatie bij het opstarten alle gebruikers
uit de database haalt en in het programma laat in een property en dat ik dan bij GetGebruikers
die property return, of moet ik bij elke methode in de factory een query via hibernate uitvoeren?
In mijn vorige projectgroep waren de meningen hierover verdeelt.
Als het de bedoeling is om je applicatie om je applicatie ten gronde te richten, en vooral te werken met 'stale' data, dan zou ik dat zeker doen ja .... :X
Ik bedoel: als je alle gegevens (die je wellicht niet eens nodig zult hebben gedurende de duur van het programma) al inlaadt, dan ga je toch echt veel geheugen gaan verbruiken, en het zal ook even duren eer alles ingeladen is, zeker als we over een grote DB spreken.
Daarnaast: wat als jij alles uit de DB trekt, een andere user doet dat ook, en past gegevens aan ? Welke gegevens ga jij dan hebben ?

ps: factory vind ik hier verkeerd gekozen qua naam; eigenlijk zou dit repository moeten heten.
Nu nog iets over de session. Nu maak ik bij elke connectie naar de database (bv. in GebruikersFactory.GetGebruikers()) een session aan, doe ik een trancactie en sluit ik de session weer. Is dit ook de bedoeling, of moet ik 1 sessie aanmaken die ik elke keer aanroep?
Je repository (factory bij jou) zou zich niet mogen moeien met het aanmaken / sluiten van connecties en transacties.
Context is king. De repository weet niet of hij een bestaande connectie moet gebruiken of niet. De repository kan ook niet weten of bepaalde objecten binnen eenzelfde transactie moeten bewaard owrden of niet.
Je applicatie / service layer / whatever / dat gebruik maakt van je repository (de laag die dus gebruikersFactory.GetGebruikers() aanroept), is de enige die weet welke sessie of transactie er moet gebruikt worden. Het is dus de 'caller' die moet bepalen of er een nieuwe transactie moet gestart worden / gecommit worden, of er een nieuwe sessie moet geopend worden, enz...
Ansur schreef op maandag 14 januari 2008 @ 12:49:
[...]


Sessies... is het een desktopapplicatie? Ik denk dat je in dat geval maar 1 sessie object nodig zal hebben.
Ehm, dat denk ik niet... :X
Waarom denk jij dat ?
Een ISession is lightweight en is helemaal niet duur om te creeëren. Als je alles in eenzelfde ISession stopt, dan heb je imho ook veel kans om met stale data te werken. Sessions moeten shortlived zijn.

[ Voor 10% gewijzigd door whoami op 14-01-2008 12:56 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Bedankt voor je antwoord.
Het wordt een webapplicatie.

Verder zullen er tussen de 50 en 100 gebruikers in de applicatie komen, dus dan zou ik deze van te voren in kunnen laden. Hoe gaat dat dan eigenlijk in zijn werk? Bij het opstarten van de applicatie op een of andere manier alle gebruikers in de property van de factory laden?

Dus eigenlijk moet ik per class / factory bekijken of het zinvol is om bij het opstarten de data in de factory te laden of dat ik per methode nhibernate aanspreek als ik het gped begrijp.

Het is inderdaad zo dat als er meerdere gebruikers gebruik maken van de applicatie je wel altijd de up-to-date info moet hebben. Dan zal je dus wel elke keer de info uit de database moeten halen.

[ Voor 15% gewijzigd door Verwijderd op 14-01-2008 12:57 ]


Acties:
  • 0 Henk 'm!

  • Cloud
  • Registratie: November 2001
  • Laatst online: 10-09 22:33

Cloud

FP ProMod

Ex-moderatie mobster

Verwijderd schreef op maandag 14 januari 2008 @ 12:54:
Verder zullen er tussen de 50 en 100 gebruikers in de applicatie komen, dus dan zou ik deze van te voren in kunnen laden. Hoe gaat dat dan eigenlijk in zijn werk?
Maar waarom zou je dit willen? :) Heb je ze allemaal nodig voor een rapportje ofzo? Ik kan geen normale reden verzinnen waarvoor je álle gebruikers uit een DB op zou willen halen. Het brengt, zoals whoami ook al zegt, nogal wat risico met zich mee met betrekking tot verouderde (stale) data.

Never attribute to malice that which can be adequately explained by stupidity. - Robert J. Hanlon
60% of the time, it works all the time. - Brian Fantana


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Klopt, dus dat ga ik niet doen. Zijn hele goede redenen om ze niet allemaal in te laden inderdaad.

Nog even over de session:
*.aspx roept de methode GetGebruikers() aan. De session wordt dus gestart in de aspx pagina, waarna de methode wordt aangeroepen en de session weer gesloten. Als er een methode wordt aangeroepen waarbij iets gewijzigd wordt word er ook een transaction in de aspx pagina gestart en na het aanroepen van de methode een update/delete aangeroepen en gesloten. Zie ik dit goed?

Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 10-09 20:32
Je bent nogal tegenstrijdig. Je zegt het volgende:
Klopt, dus dat ga ik niet doen. Zijn hele goede redenen om ze niet allemaal in te laden inderdaad.
En vervolgens zeg je
Nog even over de session:
*.aspx roept de methode GetGebruikers() aan. .......
Wat anderen ook al zeiden, WAAROM wil je alle gebruikers ophalen? Ik lees in je voorgaande posts dat je met repository's werkt. Uit die posts maak ik op dat je van plan bent om al je data van te voren in te lezen e.d. De enigste reden waarom je dit zou willen doen in een webapplicatie is omdat je rapporten genereerd voor de desbetreffende data.
En dan nog ben je meestal beter af door specifiek de data te queryen die je nodig hebt, in plaats van domweg alles van te voren in te laden.

Waarom zou je dan niet altijd direct NHibernate aanroepen? Combineer dit met de caching functionaliteit ingebouwd in NHibernate en je code is een stuk leesbaarder, maar toch de performance winst.

Je kunt overigens met de criteria api van Hibernate query criteria opgeven om zo specifieke data van nhibernate op te vragen, in plaats van alles.
De session wordt dus gestart in de aspx pagina, waarna de methode wordt aangeroepen en de session weer gesloten. Als er een methode wordt aangeroepen waarbij iets gewijzigd wordt word er ook een transaction in de aspx pagina gestart en na het aanroepen van de methode een update/delete aangeroepen en gesloten. Zie ik dit goed?
Volgens mij is het zo dat er een sessie geopend wordt op het moment dat de pagina geladen wordt, en wordt de sessie automatisch weer gesloten op het moment dat de pagina klaar is. Je hoeft dus niet na het aanroepen van een methode expliciet de sessie te sluiten (tenminste afaik, somebody correct me if im wrong :P)

Overigens misschien ook eens de moeite waard om naar ActiveRecord te kijken. Voor relatief eenvoudige webapps is ActiveRecord zeer handig.
Indien je een webapp hebt die met legacy databases en/of met dynamische entiteiten werkt dan raad ik het af.
ActiveRecord is een laag over NHibernate die het gebruik veel makkelijker maakt.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben nu niet meer van plan om alle data van te voren in te laden.
Ik moet inderdaad rapporten maken, en ben nu van plan alle gebruikers (gegevens die ik nodig heb) gewoon dmv een query direct op NHibernate op te halen.

[ Voor 8% gewijzigd door Verwijderd op 14-01-2008 14:40 ]


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:30
Je NHibernate-Sessie moet je zelf openen en zelf sluiten.

[ Voor 10% gewijzigd door whoami op 14-01-2008 14:43 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ja, dat klopt, dat heb ik ook gevonden en doe ik ook.
Ben alles even in een test-project aan het realiseren.
Ben nu verder aan het lezen over hoe ik de sessionfactory het beste kan implementeren.

http://www.theserverside....article.tss?id=NHibernate
http://www.theserverside....ticle.tss?id=NHibernateP2

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Na veel lezen heb ik nu het volgende:

Er wordt een singleton sessionfactory aangemaakt.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using NHibernate;
using NHibernate.Cfg;

namespace test.ContactDomain
{
    sealed class NHibernateSessionFactory
    {
        private Configuration cfg = null;
        private ISessionFactory factory = null;

        private NHibernateSessionFactory()
        {
            cfg = new Configuration();
            cfg.AddAssembly("test");
            factory = cfg.BuildSessionFactory();
        }

        public static readonly NHibernateSessionFactory Instance = new NHibernateSessionFactory();

        public ISession OpenSession()
        {
            return factory.OpenSession();
        }
    } 
}


Deze wordt elke keer gebruikt om een session/transaction te creeren en daarna weer gesloten.

Acties:
  • 0 Henk 'm!

  • DutchCommando
  • Registratie: November 2000
  • Laatst online: 09:21
Een goed artikel aangaande "best practices" voor NHibernate: http://www.codeproject.co...bernateBestPractices.aspx
Pagina: 1