5

Czy muszę zamknąć ISession, które są generowane przez Castle's ISessionManager dla NHibernate? Jak obsługiwać transakcje z tymi ISession? Wciąż jestem nowy w NHibernate.Lazy loading z NHibernate Castle Facility

Edit: chciałbym mieć leniwy załadunku, ale pojawia się komunikat:

Inicjowanie [nie leniwie zainicjować kolekcję rola nie sesji lub sesja została zamknięta”

Oto moja generic Repository które dziedziczą do wdrożenia konkretnych przypadkach.

[Transactional] 
public class Repository<TKey, TModel> 
    : IRepository<TKey, TModel> 
    where TKey : IComparable 
    where TModel : class 
{ 
    private readonly ISessionManager _sessionManager; 

    protected ISession Session { get { return _sessionManager.OpenSession(); } } 

    public Repository(ISessionManager sessionManager) 
    { 
     _sessionManager = sessionManager; 
    } 
    #region IRepository<TKey,TModel> Members 

    public virtual TModel Select(TKey key) 
    { 
     using (var session = _sessionManager.OpenSession()) 
     { 
      return session.Get<TModel>(key); 
     } 
    } 

    public virtual IList<TModel> SelectWhere(Func<TModel, bool> query) 
    { 
     using (var session = Session) 
     { 
      return session.Linq<TModel>().Where(query).ToList(); 
     } 
    } 

    public virtual TModel Single(Func<TModel, bool> query) 
    { 
     using (var session = Session) 
     { 
      return session.Linq<TModel>().SingleOrDefault(query); 
     } 
    } 

    public virtual TModel First(Func<TModel, bool> query) 
    { 
     using (var session = Session) 
     { 
      return session.Linq<TModel>().FirstOrDefault(query); 
     } 
    } 

    public virtual IList<TModel> All() 
    { 
     using (var session = Session) 
     { 
      return session.Linq<TModel>().ToList(); 
     } 
    } 

    [Transaction(TransactionMode.Requires)] 
    public virtual void Store(TModel entity) 
    { 
     using (var session = Session) 
     { 
      session.SaveOrUpdate(entity); 
     } 
    } 

    [Transaction(TransactionMode.Requires)] 
    public virtual void Store(IEnumerable<TModel> entities) 
    { 
     using (var session = Session) 
     { 
      foreach (TModel entity in entities) 
       session.SaveOrUpdate(entity); 
     } 
    } 


    [Transaction(TransactionMode.Requires)] 
    public virtual void Remove(TModel entity) 
    { 
     using (var session = Session) 
     { 
      session.Delete(entity); 
     } 

    } 

    public virtual void Remove(Func<TModel, bool> query) 
    { 
     IEnumerable<TModel> entities = SelectWhere(query); 
     Remove(entities); 
    } 

    [Transaction(TransactionMode.Requires)] 
    public virtual void Remove(IEnumerable<TModel> entities) 
    { 
     using (var session = Session) 
     { 
      foreach (TModel entity in entities) 
       session.Delete(entity); 
     } 
    } 

    #endregion 
} 

public class Repository<TModel> 
    : Repository<Guid, TModel>, IRepository<TModel> 
    where TModel : class 
{ 
    public Repository(ISessionManager sessionManager) : base(sessionManager) { } 
} 

public class Repository 
    : Repository<ulong, object>, IRepository 
{ 
    public Repository(ISessionManager sessionManager) : base(sessionManager) { } 
} 

Oto powołując próbka tego repozytorium:

IUserRepository userRepository = new UserRepository(); // This is actually provided by my IoC 

var users = userRepository.All(); 
foreach (var user in Users) 
{ 
    foreach (var picture in user.Pictures) 
    { 
     // I get exceptions when I do stuff like this. 
    } 
} 

Odpowiedz

6

Tak, zawsze wyrzucać ISession. Zobacz the docs on ISessionManager usage.

W przypadku transakcji rozważ użycie opcji Automatic Transaction Facility.

The SessionManager is ATM-aware dzięki temu będzie on inteligentnie, kiedy będzie trzeba, biorąc pod uwagę transakcje, nawet jeśli najwyraźniej pozbyłeś się ISession.

Here's a quick & dirty sample app który wykorzystuje Wyposażenie ASP.NET MVC + Zamek automatyczna transakcja + NHibernate siłownia

+0

Jak zrobić leniwe ładowanie? –

+0

Tym, czego naprawdę potrzebujesz, jest przykładowy kod. Zobacz http://svn.castleproject.org:8080/svn/castle/trunk/Samples/MindDump/ i testy: http://svn.castleproject.org:8080/svn/castle/trunk/Facilities/NHibernateIntegration/Castle .Facilities.NHibernateIntegration.Tests/ –

+0

Czy możesz wskazać mi plik, który pokazuje, jak działa ładowanie? –

0

Używamy transakcji z użyciem oświadczenia obsłużyć zbywania.

public void Save<K>(K entity) 
     { 

      if (entity == null) 
       throw new ArgumentNullException("item", "The item being saved cannot be null."); 

      using (ISession session = GetSession()) 
      { 
       using (ITransaction tx = session.BeginTransaction()) 
       { 
        session.SaveOrUpdate(entity); 
        tx.Commit(); 
       } 
      } 
     } 

Nadal dostanę błąd leniwego ładowania, jeśli uzyskuję dostęp do obiektów po wprowadzeniu modyfikacji w tej samej akcji. Naprawiłem błąd, nie uzyskując dostępu do obiektów po zapisie. Oto wyjaśnienie: NHibernate.LazyInitializationException

Uważam, że wynika to z niepoprawnego zapisania hierarchii. Nie testowałem tego, ale może zapisanie obiektów nadrzędnych, jeśli chcesz uzyskać do nich dostęp, naprawi problem. Po prostu umieszczenie informacji potrzebnych do uzyskania dostępu po zapisaniu do zmiennych lokalnych przed zapisaniem wydawało się poprawić mój problem.