Autofac、(流畅)nHibernate、ISession“会话已关闭!”间歇性地
我随机收到“会话已关闭!” 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();
}
}
当前设置有效,但似乎间歇性失败(在少数页面重新加载或卡西尼号重新启动),GetUsers 抛出“会话已关闭!”错误。我认为在 InstancePerHttpRequest 上注册 ISessionFactory 可以避免这些问题。运气不好。有什么想法吗? nHibernate 和 Autofac 的新手,所以如果我未能发布足够的相关信息,请告诉我。
I'm having random "Session is closed!" errors with the following configuration of Autofac and 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();
}
}
This current set-up works, but seems to fail intermittently (after a few page reloads or restarts of Cassini) with GetUsers throwing "Session is closed!" errors. I thought registering the ISessionFactory on an InstancePerHttpRequest would avoid these issues. No luck. Any ideas? New to nHibernate and Autofac, so if I failed to post enough relevant information, let me know.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
看来我的配置对于我的自定义成员资格提供程序和自定义角色提供程序之外的任何 nHibernate 调用都完美工作 - 据我所知,它们是问题所在,这意味着这个问题并没有真正解决问题。
It appears my configuration is working perfectly for any nHibernate calls outside of my custom membership providers and custom role providers - they are the issue as far as I can tell, which means this question isn't really addressing the issue.
您的
存储库
是如何注册的?是InstancePerHttpRequest
(应该是),还是Singleton
(它不应该)。How is your
Repository
registered? Is itInstancePerHttpRequest
(which is should be), orSingleton
(which it shouldn't).我在使用 MVC 3 操作过滤器时遇到了类似的问题,似乎它们在 MVC 3 中缓存得非常积极,并且发现会话并不总是打开,因为 OnActionExecuted 并不总是触发。
将会话移动到控制器构造函数中,如下所示:
在要包装事务的操作中:
I have had a similar problem using MVC 3 action filters and seems they are cached quite aggressively in MVC 3 and found that sessions were not always being opened as OnActionExecuted not always fire.
Move your session into the controller constructor like so:
In your action where you want to wrap a transaction: