2010-01-08 22 views
7

W this question zapytałem o czas życia sesji NHibernate. Używam aplikacji komputerowej, ale z separacją klient/serwer, więc wniosek jest taki, że użyję jednej sesji na żądanie serwera, ponieważ strona serwera jest miejscem, gdzie dzieje się cała magia NHibernate.Jak obsługiwać sesję NHibernate za pomocą usług?

Mój problem polega teraz na tym, jak sobie z tym poradzić. Miałem problems before z ładowaniem przywoływanych danych, gdy sesja została przedwcześnie zamknięta. Problemem jest to, że widzę po moich zajęciach przywoływanych podczas debugowania - stąd odwołanie danych nie jest jeszcze załadowany:

baza {} = {NHibernate.HibernateException "Inicjowanie [MyNamespace.Foo # 14] -failed aby leniwie zainicjować kolekcję roli: MyNamespace.Foo.Bars, sesja lub sesja nie została zamknięta "}

Z tego co rozumiem, nie ładuje się wszystkich, mimo że dokonuję transakcji. Tak więc nauczyłem się, że muszę mieć otwartą sesję przez jakiś czas, ale jak długo?

Moje pytanie brzmi w zasadzie, czy właściwie obchodzę się z życiem, lub co powinienem zmienić, aby być na dobrej drodze. Szczerze mówiąc, nie widzę, jak to może być złe, więc bardzo chciałbym wywołać funkcję, aby upewnić się, że przywoływane dane są pobierane. Jestem nie przy użyciu leniwego ładowania, więc myślałem, że zostaną one załadowane natychmiast ..?

Obecna architektura: Używanie klasy "usługowej", która wykonuje transakcję. Jest to IDisposable, więc sama usługa używa klauzuli using wokół niego. NHibernateSessionFactory dostarcza statyczną fabrykę, która zostanie ponownie wykorzystana.

// This is the service - the function called "directly" through my WCF service. 
public IList<Foo> SearchForFoo(string searchString) 
{ 
    using (var serviceBehavior = new FooServiceBehavior(new NhibernateSessionFactory())) 
    { 
     return serviceBehavior.SearchForFoo(searchString);  
    }       
} 

public class FooServiceBehavior : IDisposable 
{ 
    private readonly ISession _session; 

    public FooServiceBehavior(INhibernateSessionFactory sessionFactory) 
    { 
     _session = sessionFactory.OpenSession();     
    } 

    public void Dispose() 
    { 
     _session.Dispose(); 
    } 

    public IList<Foo> SearchForFoo(string searchString) 
    {   
     using (var tx = _session.BeginTransaction()) 
     { 
      var result = _session.CreateQuery("from Foo where Name=:name").SetString("name", searchString).List<Name>(); 
      tx.Commit(); 
      return result; 
     } 
    } 

Odpowiedz

5

Okazuje się, że w końcu robię leniwy załadunek. Miałem następujące odwzorowanie:

public class FooMapping : ClassMap<Foo> 
{ 
    public FooMapping() 
    { 
     Not.LazyLoad(); 
     Id(c => c.Id).GeneratedBy.HiLo("1"); 
     Map(c => c.Name).Not.Nullable().Length(100); 
     HasMany(x => x.Bars).Cascade.All(); 
    } 
} 

I przyjął Not.LazyLoad() wyłączoną leniwy załadunku, ale widocznie nie dla przywoływanych obiektów. Dodałem leniwy ładunek na referencji i wydaje się, że naprawiłem problem.

public class FooMapping : ClassMap<Foo> 
{ 
    public FooMapping() 
    { 
     Not.LazyLoad(); 
     Id(c => c.Id).GeneratedBy.HiLo("1"); 
     Map(c => c.Name).Not.Nullable().Length(100); 
     HasMany(x => x.Bars).Not.LazyLoad(); // <---------- 
    } 
} 

Dzięki za poświęcony czas, a ja wciąż będę zadowolony, aby zobaczyć swoje opinie, czy mój danej struktury jest uzasadnione.

-1

Jeśli do celów mapowania używane są pliki xml, możemy ustawić lazy = false dla worka.

+0

Pliki XML nie są używane do mapowania - jak widać w przykładowym kodzie. Używam Fluent do mapowania. – stiank81

Powiązane problemy