Odczyt listy z bazy danych

0

Witam!
Mam problem ze zwróceniem przez metodę Listy odczytanej z bazy danych.
Metoda GetCollectionWords odczytuje za pomocą Fluent Nhibernate z bazy danych listę obiektów CollectionWords (każdy taki obiekt posiada również listę obiektów Word) i przypisuje ją do pomocniczej listy collectionToReturn.

 public List<CollectionWords> GetCollectionWords()
        {
            List<CollectionWords> collectionToReturn = new List<CollectionWords>();
           
           
                using ( var session = NHibernateHelper.OpenSession())
                {
                    using (var transaction = session.BeginTransaction())
                    {
                        
                        var users = session.CreateCriteria(typeof(Users)).Add(Restrictions.Eq("Id", User.UserIdNumber)).List<Users>();                                                                          

                              collectionToReturn = users[0].CollectionWord.ToList<CollectionWords>();
                                                      
    
                        }

                        transaction.Commit();
                    }
                }
           

            return collectionToReturn;
        }

Kiedy odwołuję się do pól zwróconego przez GetCollectionWords obiektu to wszystko działa. Problem zaczyna się wtedy, gdy próbuję odwołać się do listy Word(List<Word>) która znajduje się w obiektach CollectionWord

private void AddColection_Click(object sender, RoutedEventArgs e)
        {
            List<CollectionWords> testList = new List<CollectionWords>();
            testList = userOperations.GetCollectionWords();
             

            foreach (var colle in testList)
              {
                textbox1.text = textbox1.text + colle.NameCollection;
                 foreach (var _word in colle.ListWords)  // !!!!!!!!! Tu wywala wyjątek !!!!!!!
                 {
                 listOfWordsToRead.Add(new Word { Question = _word.Question, Answer = _word.Answer });

                 }
              }
       }

Treść komunikatu:

failed to lazily initialize a collection of role: Test_Fluent_Login.DataBase.Entities.CollectionWords.ListWords, no session or session was closed

Jeśli wykonuje różne operacje na tej odczytanej z bazy kolekcji w metodzię GetCollectionWords to wszystko działa, więc pewnie problem jest w tym że zamyka tą sesję i nie mże się do niej odwołać.
W jaki sposób mogę rozwiązać ten problem?
Próbowałem w taki sposób dodawać obiekty do listy collectionToReturn i wtedy działa, ale nie mogę w tym sposobie zainicjalizować pola Id obiektu a(collectionWords) ponieważ jest tylko do odczytu

 foreach (var coll in users[0].CollectionWord)
      {
                 CollectionWords a = new CollectionWords { NameCollection = coll.NameCollection };
                 foreach(var _word in coll.ListWords)
                 {
                      a.ListWords.Add(new Word { Answer = _word.Answer, Question = _word.Question });
                 }
         collectionToReturn.Add(a);
     }
1

wymus egzekucje kodu. Zrob .ToList() na query wtedy NH zrobi ewaluacje i od razu pobierze dane

Ogolnie jak pobierasz dane z bazy danych to pobierasz zapytanie. I do poki nie bedziesz robic jakis operacji na tym Query to zapytanie sie nie wykona. Ale jak zrobisz ToList() na samym koncu to wymusisz egzekucje Query

1
komor98 napisał(a):

Jeśli wykonuje różne operacje na tej odczytanej z bazy kolekcji w metodzię GetCollectionWords to wszystko działa, więc pewnie problem jest w tym że zamyka tą sesję i nie mże się do niej odwołać.
W jaki sposób mogę rozwiązać ten problem?

Na dwa sposoby - albo nie zamykając sesji dopóki nie skończysz działać na danych z niej, albo pobierając powiązane rekordy zachłannie.
Jeśli masz zamiar zawsze pracować na wszystkich danych, to drugie podejście ma znacznie większy sens. Jak sądzę będzie to wyglądało mniej więcej tak:

var users = session.CreateCriteria(typeof(Users)).SetFetchMode("Words", FetchMode.Eager).Add(Restrictions.Eq("Id", User.UserIdNumber)).List<Users>();

W ogóle, to czemu używasz Criteria API, a nie QueryOver?

0

Jeszcze nigdy nie robiłem na Query a do tej pory wszystko mi działało na Criteria. A jakie są różnice między Query a Criteria i dlaczego lepiej Query?

1

Nie no, jasne, że wszystko działa na Criteria API, nie w tym rzecz. :)
QueryOver ma API działające na lambdach, a nie stringach, więc zamiast session.CreateCriteria(typeof(Users)).Add(Restrictions.Eq("Id", User.UserIdNumber)) można po prostu: session.QueryOver<Users>().Where<Users>(u => u.Id == User.UseridNumber) bez żadnych magicznych stringów i ryzyka literówki.

0

Dzięki za podpowiedź, faktycznie teraz to lepiej wygląda :) Jeszcze pytanko dotyczące tych sesji. Mam klasę w której jest kilka metod i każda z nich wykonuje jakieś operacje na bazie danych( dodaje/ wyszukuje jakieś rekordy itp.) i robię to tak że w każdej metodzie jest tworzona i otwierana sesja i transakcja. Czy to jest dobre podejście? Czy może lepiej otworzyć ją globalnie w klasie?

0

Zależ, czy te metody są wywoływane niezależnie, czy stanowią jakiś ciąg operacji w ramach jednego przypadku użycia.

0

Niezależnie, jedna np rejestruje nowego użytkownika w bazie a druga loguje użytkownika i wywołuje je w zależności od potrzeb

0

No to należy sobie zadać pytanie, czy to dobrze, że te metody są w jednej klasie, skoro są ze sobą niezwiązane?
No, ale w każdym razie, skoro transakcja w całości jest wykonywana przez taką metodę, to nie ma sensu tworzyć ich globalnie. Większy sens miałoby wstrzykiwać z zewnątrz za pomocą dependency injection.

1 użytkowników online, w tym zalogowanych: 0, gości: 1