5

¿Debo cerrar los ISession generados por Castle ISessionManager para NHibernate? ¿Cómo manejo las transacciones con esos ISession? Todavía soy bastante nuevo en NHibernate.Carga lenta con la instalación del castillo de NHibernate

Editar: me gustaría tener la carga diferida, pero me sale este mensaje:

Inicialización [Error al perezosamente inicializar una colección de papel:, ninguna sesión o sesión se cerró"

Aquí es mi repositorio genérico que heredo de implementar instancias específicas.

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

Aquí es una invocación muestra de ese repositorio:

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

Respuesta

6

Sí, siempre disponer el ISession. Ver the docs on ISessionManager usage.

Para transacciones, considere usar el Automatic Transaction Facility.

SessionManager is ATM-aware por lo que tendrá que desechar el ISession inteligentemente cuando sea necesario, teniendo en cuenta las transacciones, incluso cuando aparentemente haya dispuesto el ISession.

Here's a quick & dirty sample app que utiliza Facility ASP.NET MVC + Castillo automática de transacciones + NHibernate instalación

+0

¿Cómo hago la carga lenta? –

+0

Lo que realmente necesita es un código de muestra. Ver http://svn.castleproject.org:8080/svn/castle/trunk/Samples/MindDump/ y las pruebas: http://svn.castleproject.org:8080/svn/castle/trunk/Facilities/NHibernateIntegration/Castle .Facilities.NHibernateIntegration.Tests/ –

+0

¿Puede indicarme un archivo que muestra el funcionamiento de carga lenta? –

0

Utilizamos las transacciones con el uso de declaraciones para manejar la desecharlas.

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

Seguiré recibiendo el error de carga diferida si estoy accediendo a objetos después de realizar una modificación en la misma acción. He solucionado el error al no acceder a los objetos después de guardar. Aquí hay una explicación: NHibernate.LazyInitializationException

Creo que se debe a que no se guardó la jerarquía correctamente. No lo he probado, pero quizás guardar los objetos principales si desea acceder a ellos solucionará el problema. Simplemente poner la información que necesitaba para acceder después de guardar en variables locales antes de guardar parecía corregir mi problema.

Cuestiones relacionadas