nHibernate, LazyLoading und LazyInitializationException
-
Hi.
(Ich halte die Erklärungen relativ kurz. Wer mit nHibernate vertraut ist wird das Problem sofort verstehen)
Außerhalb einer nHibernate-Session funktioniert LazyLoading nicht. Die Session will ich nicht offen halten (Winforms-Anwendung) und suche jetzt eine andere Lösung.
//Die Entitäten. Benutzer und Kommentare von diesem Benutzer z.B. in einem Forum (Fantasiecode). //Es besteht eine one-to-many-Beziehung aus Sicht des Users. public class User { public virtual int Id { get; set; } public virtual string NickName { get; set; } private ISet<Comment> comments = new HashedSet<Comment>(); public virtual ISet<Comment> Comments { get { return comments; } set { comments = value; } } } public class Comment { public virtual int Id { get; set; } public virtual string Text {get; set;} } ////////////////////////////////////////////////////////////////////////////////////////// //Verwendung in der GUI var list = userStorage.GetAll(); //Alle User laden. foreach (User user in list) { Console.WriteLine(user.Nickname); //Klappt Console.WriteLine(user.comments.Count); //LazyInitializationException }
Das XML-Mapping ist trivial und erspare ich euch (LazyLoading ist default).
Die comments sollen "Lazy" geladen werden. Das geht aber schief weil nHibernate aus mir nicht ersichtlichen Gründen nicht
in der Lage ist, selbstständig eine neue Session zu öffnen.Hier meine unschöne Lösung:
//Code für userStorage public class GenericStorage<Entity> where Entity : class { public virtual void Lock(Entity entity, Action action) { using (ISession session = sessionFactory.OpenSession()) { session.Lock(entity, NHibernate.LockMode.None); action(); } } } //Wieder in der GUI var list = userStorage.GetAll(); foreach (User user in list) { Console.WriteLine(user.Nickname); userStorage.Lock(user, () => { Console.WriteLine(user.comments.Count); } }
Die Lösung ist also, die user-Objekte im "detached"-Zustand wieder explizit in den "persistent"-Zustand zu überführen.
Damit ziehen sich Implementierungsdetails der Datenschicht bis zur GUI durch!Das kann doch nicht die Lösung sein.Hat jemand eine bessere Lösung? (Lazy-Loading ist erwünscht! Eine andere Fetching-Strategie bringt mir im Anwendungsfall nichts)
Danke, µ