使用NHibernate Castle Facility延迟装载

时间:2009-07-13 03:55:20

标签: nhibernate castle-windsor lazy-loading castle windsor-nhfacility

我是否必须关闭Castle的ISession为NHibernate生成的ISessionManager?如何处理那些ISession的交易?我对NHibernate还不熟悉。

编辑:我想延迟加载,但收到此消息:

  

初始化[懒得懒散   初始化角色集合:,没有   会议或会议已经结束“

这是我继承的通用存储库,用于实现特定的实例。

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

以下是调用该存储库的示例:

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

2 个答案:

答案 0 :(得分:6)

是的,始终处置ISession。请参阅the docs on ISessionManager usage

对于交易,请考虑使用Automatic Transaction Facility

SessionManager is ATM-aware所以它会在需要时巧妙地处理ISession,将交易考虑在内,即使您显然已经处理了ISession

Here's a quick & dirty sample app使用ASP.NET MVC + Castle自动事务处理工具+ NHibernate工具

答案 1 :(得分:0)

我们使用using语句来处理处理。

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

如果我在同一个动作中进行修改后访问对象,我仍然会收到延迟加载错误。我通过在保存后不访问对象来修复错误。这是一个探索:NHibernate.LazyInitializationException

我认为这是因为没有正确保存层次结构。我还没有对它进行过测试,但是如果您希望访问它们,可能会保存父对象将解决问题。在保存之前保存到局部变量之后,简单地输入我需要访问的信息似乎可以纠正我的问题。