5

Devo chiudere lo ISession generato da Castle's ISessionManager per NHibernate? Come gestisco le transazioni con quelle ISession? Sono ancora abbastanza nuovo di NHibernate.Caricamento lento con NHibernate Castle Facility

Edit: Mi piacerebbe avere lazy loading, ma ottengo questo messaggio:

inizializzazione [non è riuscito a pigramente inizializzare una collezione di ruolo:, nessuna sessione o la sessione è stata chiusa"

Ecco il mio repository generico che ho ereditato da implementare istanze specifiche.

[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) { } 
} 

Ecco un esempio di invocazione che repository:

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. 
    } 
} 

risposta

6

Sì, smaltire sempre la ISession. Vedi the docs on ISessionManager usage.

Per le transazioni, prendere in considerazione l'utilizzo di Automatic Transaction Facility.

Il SessionManager is ATM-aware in modo che disporrà l'ISession elegantemente quando è necessario, tenendo le transazioni in considerazione, anche quando apparentemente non hanno smaltito la ISession.

Here's a quick & dirty sample app che utilizza ASP.NET MVC + Castello automatico Transaction Struttura impianto + NHibernate

+0

Come si esegue il caricamento lazy? –

+0

Ciò di cui hai veramente bisogno è un codice di esempio. Vedi http://svn.castleproject.org:8080/svn/castle/trunk/Samples/MindDump/ e i test: http://svn.castleproject.org:8080/svn/castle/trunk/Facilities/NHibernateIntegration/Castle .Facilities.NHibernateIntegration.Tests/ –

+0

Puoi indicarmi un file che mostra il funzionamento di caricamento lento? –

0

Usiamo le transazioni con l'utilizzo di dichiarazioni per gestire la Smaltimento.

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(); 
       } 
      } 
     } 

sarò ancora ottenere l'errore lazy loading se io sono l'accesso degli oggetti dopo aver fatto una modifica nella stessa azione. Ho risolto l'errore non accedendo agli oggetti dopo un salvataggio. Ecco un'esplosione: NHibernate.LazyInitializationException

Credo che sia dovuto a non salvare correttamente la gerarchia. Non l'ho provato, ma forse il salvataggio degli oggetti padre se si desidera accedervi risolverà il problema. Semplicemente inserendo le informazioni di cui avevo bisogno per accedere dopo il salvataggio in variabili locali prima che il salvataggio sembrasse correggere il mio problema.