2009-07-08 9 views
0

Je viens de commencer à utiliser NHibernate, et j'ai quelques problèmes que je ne sais pas comment résoudre correctement.Sessions NHibernate - quelle est la manière courante de gérer les sessions dans les applications Windows?

J'ai commencé par créer un référentiel générique contenant CUD et quelques méthodes de recherche. Chacune de ces méthodes ouvre une session distincte (et une transaction si nécessaire) pendant les opérations de la base de données. Le problème lorsque je fais cela (pour autant que je sache) est que je ne peux pas tirer parti du chargement paresseux des collections/objets associés. Dans le mappage fluide, presque toutes les relations d'entité ont .Not.LazyLoad(), il en résulte que la base de données entière est chargée lorsque je demande une liste de toutes les entités d'un type donné.

-moi si je me trompe, parce que je suis encore un débutant complet quand il vient à NHibernate :)

Quelle est la plus courante de faire pour éviter cela? Avoir une session statique globale qui reste en vie tant que le programme s'exécute, ou que dois-je faire?


Une partie du code référentiel:

public T GetById(int id) 
{ 
    using (var session = NHibernateHelper.OpenSession()) 
    { 
     return session.Get<T>(id); 
    } 
} 

Utilisation du référentiel pour obtenir une personne

var person = m_PersonRepository.GetById(1); // works fine 

var contactInfo = person.ContactInfo; // Throws exception with message: 

// failed to lazily initialize a collection, no session or session was closed 

Répondre

3

Votre question se résume en fait vers le bas pour objet la mise en cache et la réutilisation. Si vous chargez un objet Foo à partir d'une session, pouvez-vous le garder, puis, à un moment ultérieur, charger paresseusement sa propriété Barre? Chaque instance ISession est conçue pour représenter une unité de travail, et est livrée avec un cache de premier niveau qui vous permettra de récupérer un objet plusieurs fois dans cette unité de travail, mais qui n'aura qu'une seule base de données. Il n'est pas sûr pour les threads et ne devrait certainement pas être utilisé comme objet statique dans une application WinForms.

Si vous souhaitez utiliser un objet lorsque la session sous laquelle il a été chargé a été éliminée, vous devez l'associer à une nouvelle session à l'aide de Session.SaveOrUpdate (objet) ou Session.Update (objet).

Vous pouvez trouver tout ceci expliqué dans chapter 10 of the Hibernate documentation.

Si cela semble inefficace, examinez la mise en cache de second niveau. Ceci est fourni au niveau de ISessionFactory - votre fabrique de sessions peut être statique, et si vous activez la mise en cache de second niveau, cela générera efficacement un cache en mémoire de la plupart de vos données. La mise en cache de second niveau n'est appropriée que s'il n'y a pas de service sous-jacent mettant à jour vos données - si toutes les mises à jour de base de données passent par NHibernate, alors elle est sûre.

Modifier à la lumière d'un code affiché

Votre utilisation de session est au mauvais niveau - que vous utilisez pour une base de données unique obtenir, au lieu d'une unité de travail. Dans ce cas, votre méthode GetById doit prendre une session qu'il utilise et l'instance de session doit être gérée à un niveau supérieur. Alternativement, votre classe PersonRepository devrait gérer la session si vous préférez, et vous devriez instancier et disposer un objet de ce type pour chaque unité de travail.

public T GetById(int id) 
{ 
    return m_session.Get<T>(id); 
} 

using (var repository = new PersonRepository()) 
{ 
    var person = repository.GetById(1); 
    var contactInfo = person.ContactInfo; 
} // make sure the repository Dispose method disposes the session. 

Le message d'erreur que vous obtenez est parce qu'il n'y a plus d'une session à utiliser pour charger la paresseuse collection - vous avez déjà disposé elle.

+0

Merci pour votre réponse. J'ai lu le chapitre de la documentation, mais je ne comprends toujours pas ce que vous voulez dire dans la deuxième phrase. Voulez-vous dire que je dois maintenir la session si j'ai besoin d'accéder à des propriétés chargées paresseuses? Je vais ajouter une partie de mon code de dépôt à la question. – l3dx

+0

Bien sûr - ajouter un peu de contexte à la question et je l'aborderai plus spécifiquement dans la réponse. –

+0

Nice, merci beaucoup! +1 Je retravaillerai mon dépôt ensuite :) Je crois comprendre que les choses session/db devraient être "superposées" à partir de l'application, donc si je le supprime du dépôt, où le placerais-je? – l3dx

Questions connexes