Autofac, (Свободно) nHibernate, ISession "Сессия закрыта!" с перерывами - PullRequest
3 голосов
/ 14 февраля 2012

У меня случайно "Сессия закрыта!" ошибки со следующей конфигурацией Autofac и Fluent nHibernate:

Global.asax.cs:

builder.Register(x => new NHibernateConfigurator().GetSessionFactory()).SingleInstance();
builder.Register(x => x.Resolve<ISessionFactory>().OpenSession()).InstancePerHttpRequest();

NHibernateConfigurator.cs

    public class NHibernateConfigurator
{
    public Configuration Configure()
    {
        var configuration = new Configuration();
        configuration.SessionFactory()
            .Proxy.Through<ProxyFactoryFactory>()
            .Integrate.Using<Oracle10gDialect>();

        FluentConfiguration fluentConfiguration = Fluently.Configure(configuration);
        fluentConfiguration.Mappings(m => m.FluentMappings.AddFromAssemblyOf<UserMap>());

        return fluentConfiguration.BuildConfiguration();
    }

    public ISessionFactory GetSessionFactory()
    {
        var configuration = Configure();
        return configuration.BuildSessionFactory();
    }
}

SomeController.cs:

private readonly IRepository repository;

public SomeController(IRepository repository)
{
this.repository = repository
}

[Transaction]
public ActionResult Index()
{
    var result = repository.GetUsers();
    return View(result);
}

TransactionAttribute.cs

public class TransactionAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        DependencyResolver.Current.GetService<ISession>().BeginTransaction(IsolationLevel.ReadCommitted);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ITransaction currentTransaction = DependencyResolver.Current.GetService<ISession>().Transaction;

        if (currentTransaction.IsActive)
        {
            if (filterContext.Exception != null && filterContext.ExceptionHandled)
            {
                currentTransaction.Rollback();
            }
        }
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        ITransaction currentTransaction = DependencyResolver.Current.GetService<ISession>().Transaction;

        base.OnResultExecuted(filterContext);
        try
        {
            if (currentTransaction.IsActive)
            {
                if (filterContext.Exception != null && !filterContext.ExceptionHandled)
                {
                    currentTransaction.Rollback();
                }
                else
                {
                    currentTransaction.Commit();
                }
            }
        }
        finally
        {
            currentTransaction.Dispose();
        }
    }
}

IRepository.cs:

public interface IRepository 
{
    IList<User> GetUsers();     
}

Repository.cs:

public class Repository : IRepository
{
    private readonly ISession session;

    public Repository(ISession session)
    {
        this.session = session;
    }

    public IList<User> GetUsers()
    {
        return session.QueryOver<User>().List();
    }
}

Эта текущая установка работает, но, похоже, периодически прерывается (после нескольких перезагрузок страницы или перезапуска Cassini), когда GetUsers выдает «Session is closed!» ошибки. Я думал, что регистрация ISessionFactory в InstancePerHttpRequest позволит избежать этих проблем. Неудачно. Есть идеи? Новое в nHibernate и Autofac, поэтому, если мне не удалось опубликовать достаточно актуальной информации, сообщите мне.

Ответы [ 3 ]

1 голос
/ 15 февраля 2012

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

0 голосов
/ 14 февраля 2012

У меня была похожая проблема с использованием фильтров действий MVC 3, и, похоже, они довольно агрессивно кэшируются в MVC 3, и обнаружил, что сессии не всегда открывались, так как OnActionExecuted не всегда срабатывает.

Переместите сеанс вКонструктор контроллера выглядит так:

 public SomeController(
        ISession session,
        ILogger logger,
        IRepository<Something> someRepository )
    {
        _session = session;
        _logger = logger;
        _someRepository = someRepository;
    }

В вашем действии, где вы хотите заключить транзакцию:

using (var transaction = _session.BeginTransaction())
{
   // do something with your repository
   _someRepository.Add(new Something());
   transaction.commit();
}
0 голосов
/ 14 февраля 2012

Как ваша Repository зарегистрирована?Это InstancePerHttpRequest (что должно быть) или Singleton (что не должно).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...