DAL avec NHibernate en mode déconnecté
Bonjour,
Je développe une application Winform et j'utilise NHibernate pour l'accès aux données.
J'essaye architecturer mon application selon les préconisations de nos amis Sami Jabber ou Thomas Lebrun (CF Introduction au développement en couches) (Merci à eux au passage)
de manière à avoir :
- une couche présentation des données => Winform
- une couche de service qui propose de récupérer, mettre à jour des objets ou liste d'objets métiers (sans notion de session :erreur ?)
- une couche d'accès au données qui encapsule NHibernate.
Le problème c'est que lorsque dans ma couche de présentation j'utilise un objet métier par exemple Client , j'ai parfois (pas nécessairement) besoin d'accéder aux attributs d'objets référencés par cet objet Client par exemple Client.Commandes ou Client.Adresse.
Mais comme je suis hors transaction, NHibernate me renvoi une exception par exemple : "failed to lazily initialize a collection, no session or session was closed"
Dans ma méthode ClientDao.ClientById(int) je ne peux pas charger toutes les dépendences systématiquement sinon je risque de remonter une bonne partie de la base pour la moindre petite opération !
Est-ce que je dois donc avoir plusieurs méthodes en fonction des usages ?
par exemple :
ClientDao.GetClientById(int oid) // Charge l'objet avec seulement les attributs simples
ClientDao.GetClientById(int oid, bool getAdresse) // Charge l'objet et l'objet référencé Adresse
ClientDao.GetClientById(int oid, bool getAdresse, bool getCommandes) // charge l'objet complet Client et ses dépendances
Problème avec cette approche :
Dans une form j'utilise ClientDao.GetClientById(int oid, bool getAdresse) mais je souhaite obtenir des infos sur un objet référencé par Client.Adresse qui n'est pas chargé (Adresse référence un objet Etablissement).
Dois-je créer une nouvelle méthode sur ClientDao pour cet usage ?
A part créer une session (Nhibernate.ISession directement (entorse à la séparation) ou un wrapper de Session) dans ma couche de présentation qui me permettrai de charger des objets référencés à la demande, je ne vois pas comment faire sinon ça risque d'être un "joyeux bordel" dans mon DAO ; les programmeurs de la couche présentation ne seront pas vraiment quelle méthode prendre et/ou voudront accéder quelque fois à des objets non chargés (et obtiendront inévitablement une exception)...
Tout ceci est dû, je pense au fait que je travaille en mode "déconnecté" : ma couche de service charge des objets, les détache (ferme la session), travaille avec et éventuellement les ré-attache (les réinjecte dans une autre session par ex pour faire un SaveOrUpdate), dans ma couche de service je n'ai pas (encore) de notion de session.
N'hésitez pas à me répondre, si vous avez des conseils, des urls de tutoriaux et pour me dire comment vous faites de votre côté.
Fx
nb: Faisons abstraction ici du nommage "franglais" c'est pour essayer de mieux me faire comprendre ;)
NHibernate en winforms et lazy propriétés...
Salut,
J'ai écrit deux articles (en anglais) sur les sujet de l'utilisation de NH dans une application winforms.
En gros, il s'agit d'un sujet assez délicat- si tu laisse la session ouvert, tu risque d'avoir de sessions énormes et probablement polluées... Donc, il te faudra de faire des aller-retour à la base chaque fois, ce qui veux dire que ce sera plus sensible de charger avant en une seule fois le plus d'info possible (ce qu'il te faut vraiment - pas plus ni moins...) et puis chaque fois que t'en a besoin, ouvrir une session pour chercher les refs demandés...
Pour cela je te conseille d'utiliser spring.net ou n'importe qu'elle autre utilitaire AOP pour remplacer les using de Transaction et session.Open()/Flush()/Close() par des 'attributes' ([Transaction]).
Il faut aussi se souvenir de jamais charger des objet et oublier fermer la session!! (-avec spring.net ça veut dire toujours utiliser le [Transaction] attribute, même pour les transaction read only...)
et oui, désolé pour mon français :oops:
j'espère que ça t'aidait ;)