3

У меня случайная «Сессия закрыта!» Ошибки со следующей конфигурацией Autofac и Fluent NHibernate:Autofac, (Свободно) nHibernate, ISession «Сессия закрыта!» с перерывами

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

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

+0

Вы используете MVC 3? Управление транзакциями управляется фильтром действий? – Chev

+0

MVC 3, да. Управление транзакциями, да. Забыл включить этот фрагмент - добавил его. – heyseuss

+0

Имел ту же проблему. Кажется, это проблема MVC 3, не могу найти ссылку на информацию, но переместите ISession, чтобы она была введена в контроллер. Почини. Лучше иметь контроль над сеансом, так что вам не нужно ждать, пока запрос не закроется, прежде чем у вас возникнет проблема, которая может возникнуть в вашем пользовательском интерфейсе. – Chev

ответ

1

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

+0

Пожалуйста, добавьте несколько журналов, чтобы проверить, что фильтры действий. Мы узнали об этом только в среде prod, при которой на нее бросали ТЯЖЕЛЫЙ трафик – Chev

0

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

+0

Currrently, как «builder.RegisterType ();". Присоединение .InstancePerHttpRequest() после As () не решило проблему (предполагая, что это вы имели в виду). – heyseuss

0

У меня была аналогичная проблема с использованием фильтров действий 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(); 
} 
Смежные вопросы