asp.net-mvc-3 – 用于Nhibernate事务管理的ActionFilter是一个
我有以下包装器:
public interface ITransactionScopeWrapper : IDisposable { void Complete(); } public class TransactionScopeWrapper : ITransactionScopeWrapper { private readonly TransactionScope _scope; private readonly ISession _session; private readonly ITransaction _transaction; public TransactionScopeWrapper(ISession session) { _session = session; _scope = new TransactionScope(TransactionScopeOption.Required,new TransactionOptions {IsolationLevel = IsolationLevel.ReadCommitted}); _transaction = session.BeginTransaction(); } #region ITransactionScopeWrapper Members public void Dispose() { try { _transaction.Dispose(); } finally { _scope.Dispose(); } } public void Complete() { _session.Flush(); _transaction.Commit(); _scope.Complete(); } #endregion } 在我的ActionFilter中,我有以下内容: public class NhibernateTransactionAttribute : ActionFilterAttribute { public ITransactionScopeWrapper TransactionScopeWrapper { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { } public override void OnActionExecuted(ActionExecutedContext filterContext) { TransactionScopeWrapper.Complete(); base.OnActionExecuted(filterContext); } } 我正在使用Castle来管理我的ISession,使用每个Web请求的生活方式: container.Register( Component.For<ISessionFactory>().UsingFactoryMethod( x => x.Resolve<INHibernateInit>().GetConfiguration().BuildSessionFactory()).LifeStyle.Is( LifestyleType.Singleton)); container.Register( Component.For<ISession>().UsingFactoryMethod(x => container.Resolve<ISessionFactory>().OpenSession()). LifeStyle.Is(LifestyleType.PerWebRequest)); container.Register( Component.For<ITransactionScopeWrapper>().ImplementedBy<TransactionScopeWrapper>().LifeStyle.Is( LifestyleType.PerWebRequest)); 所以现在回答我的问题. >以这种方式管理交易的任何问题 我问第2,因为不保证BeginRequest和EndRequest在同一个线程上运行,如果你在它们上面抛出交易,你将遇到大问题. 在我的ActionFilter中,TransactionScopeWrapper是属性注入的. 解决方法
您还应该考虑其他一些方面.
首先我想说的是决定在哪里处理您的交易.请注意,如果您使用延迟加载并将数据实体传递回视图并访问配置为延迟加载的属性或引用,则会遇到问题,因为您的事务已在OnActionExecuted中关闭.虽然我知道您应该只在视图中使用视图模型,但有时实体更方便一些.无论您是否想要使用延迟加载并在视图中访问它们,您必须将事务完成移动到OnResultExecuted方法中,以便不会过早地提交它. 其次,您还应该在提交事务之前检查是否存在任何异常或模型错误.我最终使用here和here的灵感来处理我的nHibernate事务处理的最终过滤器. 第三,如果您决定在OnResultExecuted处理程序中处理您的事务,如果它是对子操作的请求,则不会这样做.原因是,像我一样,我将会话限定为Web请求,但我发现子操作不算作新请求,当他们被调用时,他们尝试打开自己的会话,他们正在获取已经打开的会话上下文代替.当子动作完成后,它试图关闭ITS会话,但实际上也关闭了父视图使用的会话.这导致依赖于延迟加载数据的子操作失败后的任何逻辑. 我想通过尝试从我的应用程序中删除我的延迟加载数据,但是直到我有时间这样做,你应该知道可能出现的这些问题. 当我意识到我需要修复一些干燥问题时,我打算发布自己的动作过滤器.足以说我正在检查filterContext.Exception和filterContext.ExceptionHandled以查看是否有任何错误以及是否已经处理过它们.请注意,仅仅因为处理了异常并不意味着您的事务可以提交.虽然这对您的应用程序编码方式更为主观,但您也可能需要在提交事务之前检查filterContext.Controller.ViewData.ModelState.IsValid. 更新:与您不同,我使用的是StructureMap,而不是Castle for Dependency Injection,但在我的情况下,我将此行添加到gobal.asax文件中的Application_EndRequest方法作为最后一点清理.我假设城堡里有类似的东西? 更新2:无论如何,更直接地回答你的问题.我没有看到使用像你选择的包装器有什么问题,虽然我不确定为什么你觉得需要包装它? nHibernate在处理事务本身方面做得非常好,因此我不需要另外的抽象层.您可以轻松地在OnActionExecuting中显式启动事务,并在OnActionExecuted中明确地完成它.通过DependencyResolver检索ISession对象,您可以消除线程安全所带来的任何问题,因为IoC容器是线程安全的,我相信,从那里您可以使用Session.Transaction获取当前事务并从IsActive属性检查它的当前状态.我的理解是,这两种方法可能在不同的线程上发生,特别是在处理从AsynController继承的类上的操作时. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 需要有关ASP.NET本地化的建议 – 存储在数据库中并显示在gr
- asp.net – 从Mvc Action中获取WebApi UrlHelper的实例
- asp.net – 临时环境应该与现场环境相等多少?
- ASP.NET WebApi使用Swagger做接口文档
- asp.net-mvc-3 – MvcMiniProfiler 1.9 – VS或运行时无法识
- asp.net – SelectedValue是无效的,因为它不存在于项目列表
- asp.net-mvc – MVC4是否被烘烤到.NET 4.5?
- ASP.NET Core的Kestrel服务器
- unit-testing – 对ActionFilter进行单元测试 – 正确设置A
- asp.net-mvc – 从asp.net mvc控制器返回一个js文件
- asp.net – 无法识别配置文件Web.config
- asp.net-mvc – 使用ASP.net MVC项目作为其他MVC
- asp.net-mvc-3 – 将复选框绑定到MVC中的int数组
- asp.net – 处理您的请求时发生异常.此外,执行自
- asp.net – 使用ModalPopupExtender而不必设置Ta
- asp.net-mvc – 不要在JSON中序列化Entity Frame
- asp.net:控件/页面的页面生命周期顺序与其中的用
- asp.net-web-api – ASP.net 5中的IApplicationB
- 根据ASP.NET中的角色设置auth cookie超时长度
- asp.net-mvc-3 – 从ASP MVC 3 Preview更新到Bet