NHibernate LazyInitializationException .. Comment prévenir?
J'obtiens le message d'erreur suivant sur notre serveur web de production:
NHibernate.LazyInitializationException
:
Initializing[Domain.Entities.AudienceTypes.Region#4]-failed to lazily initialize a
collection of role: Domain.Entities.AudienceTypes.Region.PeerGroups,
no session or session was closed
qui n'est pas bon. La seule façon d'obtenir la demande de travail est à nouveau pour réinitialiser IIS, ce qui n'est pas vraiment une option. Qu'est-ce que cela signifie? Comment puis-je l'empêcher?
source d'informationauteur DaveDev
Vous devez vous connecter pour publier un commentaire.
Relations, par défaut, sont paresseux. Cela signifie que la requête SQL pour charger la relation n'est exécutée que lorsque vous accédez à la propriété que détient la relation.
Le problème est que si vous avez accès à un paresseux de la propriété, qui n'a jamais été appelé avant, avec la clôture de la session, puis vous obtenez cette erreur.
Vous avez des solutions:
Pour éviter ce problème, vous devez modifier référence pour PeerGroups dans votre Région de la cartographie ci-dessous
Ajoutant Chercher.Join() permettra d'éviter LazyInitializationException.
À ne pas fermer la session jusqu'à ce que vous avez terminé de travailler avec l'objet.
C'est l'un des plus grands défis de travailler avec NHIbernate à mon humble avis: la définition de la session-limites.
Dans un ASP.NET demande, il est assez facile: la séance commence au début de la demande, et vous pouvez fermer la session à la fin de la demande.
Dans une application WinForms, c'est un peu plus difficile: vous aurez à définir clairement les limites de quand une session est démarrée, et lorsque la session est fermée.
Dans les applications WinForms, j'ai généralement à définir les "Tâches" qui représentent une sorte d'Unité De Travail. Chaque Tâche a une session. La session est créée /ouvert lorsqu'une Tâche est créée, et fermé quand la Tâche est terminée.
À côté de cela, vous pouvez également définir certaines associations comme non-paresseux. Cependant, vous devez vous assurer que la performance n'est pas affectée si vous faites cela.
Plus de Frederik et lujop réponses, si vous travaillez sur un ASP.NET application (comme suggéré par votre mention d'un serveur web), c'est une bonne idée d'utiliser un framework injection de dépendance (tels que le Château d'Windor) pour gérer le cycle de vie de votre ISessions. Le château de Windsor est un mode de vie paramètre 'PerWebRequest" qui fait cela pour vous.
À défaut, créer manuellement un ISession au début de chaque demande qui est détruit (éventuellement automatiquement le rinçage lui-même) à la fin de la demande. Ensuite, votre application peut utiliser ce ISession.
C'est certainement à voir avec un ISession être fermé avant que vous pensez qu'elle est.