2010-12-08 36 views
2

Je travaille sur un projet NHibernate et j'ai rencontré des difficultés pour charger les collections plus tôt (http://stackoverflow.com/questions/4213506/c-hibernate-criteria-loading- collection), j'ai maintenant des problèmes pour utiliser les données. J'utilise C# en combinaison avec le framework NHibernate et Spring.Net, et j'obtiens une exception LazyInitializationException après avoir chargé par exemple un ordercredit, puis accédé à un objet du ordercredit.C# NHibernate avec Spring LazyInitializationException lors de l'utilisation des données

J'utilise ce code pour obtenir le OrderCredit:

OrderCredit oc = CreditService.getOrderCredit(ordercredit.Id); 

Le code que j'utilise pour le chargement est effectué en utilisant une implémentation DAO:

[Transaction(TransactionPropagation.Required, ReadOnly = true)] 
public OrderCredit GetOrderCredit(long ordercreditid) 
{ 
    var creditrules = Session.CreateCriteria(typeof(OrderCredit)); 
    creditrules.Add(Restrictions.Eq("Id", ordercreditid)); 
    return creditrules.List<OrderCredit>()[0]; 
} 

Quand je lance ce sur ma machine locale, tout ça marche très bien, et j'avais l'intention de charger une liste de ces 'ordercredits', mais cela s'est mal passé aussi, donc j'ai d'abord essayé une étape plus simple.

Les objets dans le 'OrderCredit' sont définis comme [OneToMany].

Quand je mets cela sur le testserver, et essayer d'accéder à l'objet « OrderObject » du OrderCredit chargé, je reçois l'erreur:

NHibernate.LazyInitializationException: Initialiser [.OrderObject # 5496522] -Pourriez pas initialize proxy - pas de session.

Code qui échoue:

Log.Debug(oc.OrderObject.Name); 
code

qui fonctionne:

Log.Debug(oc.Id); 

Cela se produit pour tout objet qui fait partie de la OrderCredit, mais je suis en mesure d'accéder aux champs de propriété du OrderCredit (par exemple le OrderCredit.Id).

De même, lorsque j'accède à l'un des objets AVANT de renvoyer les données à la fonction d'origine appelant la méthode, alors il cache l'information ou alors, comme je peux y accéder ensuite. J'ai lu beaucoup de choses sur ce problème, comme désactiver Lazy, mais cela n'a pas fonctionné pour moi non plus (ou je l'ai fait au mauvais endroit). Ce qui me contrarie le plus, c'est le fait que cela fonctionne sur ma machine locale, et non sur le serveur de tests. Que pourrais-je faire de mal?

Toute aide est fortement appréciée.

1ère mise à jour:

J'utilise maintenant un GenericDao, en utilisant la méthode par défaut de chargement 1 ordercredit. J'utilise le code suivant pour charger 1 ordercredit par Id.

OrderCredit oc = GenericService.Load<OrderCredit>(Id); 

Le code qui est à l'intérieur du GenericDAO est le suivant, mais il ne se termine pas ou brise la session, ce qui signifie que je suis en mesure d'accéder aux objets attachés au ordercredit:

[Transaction(TransactionPropagation.Supports, ReadOnly = true)] 
public T Load<T>(long id) where T : ISaveableObject 
{ 
    var obj = Session.Load<T>(id); 
    return obj; 
} 

C'est presque le même code que j'avais dans la fonction que j'ai incluse plus tôt dans cette question.

Je suis maintenant vraiment confus parce que je ne sais pas ce qui pourrait mettre fin à la session. Je vais travailler dessus maintenant car cela fonctionne, mais je veux le changer plus tard, donc je peux utiliser ma fonction pour appeler toute la collection et y accéder via un pour chaque boucle.

Actuellement, j'utilise ma fonction 'getOrderCredits' pour obtenir la liste des objets OrderCredit, et dans foreach, j'obtiens l'Id, et j'utilise GenericDao.Load pour obtenir l'objet réel, et je peux accéder aux objets et autres . Bien sûr, ce n'est pas ce qu'il devrait être et ce qu'il devrait être.

Je serais étonné si je suis résolu.

+0

Où ouvrez-vous et fermez-vous la session NH? Ce message d'erreur suggère que la session NH a été fermée au moment de la tentative de chargement paresseux. –

+0

C'est une extension que je fais d'un projet de travail. Les transactions sont traitées par le gestionnaire de transactions Hibernate/Spring. J'ai essayé différentes choses, et est venu à un petit travail autour. Je vais modifier ma question, et ajouter cette information et le code, comme je ne comprends pas ce que c'est que c'est mal dans ma situation. – Honnes

Répondre

4

Il s'agit d'un problème fréquent lors de l'utilisation de NHibernate. Cela arrive parce que:

  1. Vous ouvrez une session
  2. Vous chargez une entité de la base de données qui fait référence à une autre entité
  3. Vous fermez la session
  4. Vous essayez d'accéder à une propriété sur votre entité référencée
  5. NHibernate tente de charger paresseusement l'entité à partir de la base de données en utilisant la même session qui a chargé l'entité parente
  6. La session est fermée, ainsi NHibernate lève des exceptions comme woah.

Vous avez quelques options:

  1. Gardez votre session ouverte plus, de préférence en utilisant quelque chose comme l'unité de modèle de travail, qui vous donnera un contrôle plus serré.
  2. charger vos Ardemment entités référencées lorsque vous interrogez:

Dans votre cas, le printemps gère votre transaction pour vous la 2ème option est probablement le plus rapide/solution la plus simple.

var creditrules = Session.CreateCriteria(typeof(OrderCredit)); 
creditrules.Add(Restrictions.Eq("Id", ordercreditid)) 
    .SetFetchMode("OrderObject", FetchMode.Eager); 

Cela va charger le OrderObject lorsque vous chargez le OrderCredit.

+0

Merci pour votre contribution! Je dois ajouter que je ne peux plus le tester maintenant car je ne travaille plus sur ce projet, mais j'apprécie votre contribution. Puisque je ne peux pas le tester, il ne serait pas tout à fait juste de marquer votre réponse comme une réponse acceptée, n'est-ce pas? – Honnes

+0

Je ne suis pas à la recherche d'une acceptation, j'essaie simplement d'aider. – jonnii