Ленивая загрузка с NHibernate Castle Facility - PullRequest
5 голосов
/ 13 июля 2009

Должен ли я закрыть ISession, которые генерируются замком ISessionManager для NHibernate? Как мне обрабатывать транзакции с этими 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 ]

6 голосов
/ 13 июля 2009

Да, всегда утилизируйте ISession. См. документы по ISessionManager использованию .

Для транзакций рассмотрите возможность использования Автоматических транзакций .

SessionManager поддерживает ATM , поэтому он будет разумно распоряжаться ISession, когда это необходимо, с учетом транзакций, даже если вы, очевидно, располагали ISession.

Вот пример быстрого и грязного приложения , в котором используется ASP.NET MVC + средство автоматической транзакции Castle + средство NHibernate

0 голосов
/ 16 июля 2009

Мы используем транзакции с использованием операторов для обработки утилизации.

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

Я полагаю, это связано с неправильным сохранением иерархии. Я не проверял это, но, возможно, сохранение родительских объектов, если вы хотите получить к ним доступ, решит проблему. Просто поместив информацию, необходимую для доступа после сохранения, в локальные переменные, прежде чем сохранение, казалось, решило мою проблему.

...