使用Asp.Net MVC进行自动交易的最佳方法是什么?

3

我在我的MVC应用程序中反复写以下代码,感到很烦恼。

using(var tx = new TransactionScope()){
   blah...
   tx.Complete()
}

我希望以某种方式使这个代码更DRY。
我想到了几个不同的选项。
1.使用操作过滤器来声明性地标记某些操作为事务性。
2.在控制器基类中重写OnActionExecuting,并一次性使所有操作都具有事务性。
这两个选项中是否有一个好主意?有什么需要注意的地方吗?第二个选项似乎是引起死锁的好方法。
哦,对了,我还使用StructureMap和自定义控制器工厂将依赖项注入到我的控制器中,如果有人知道一些注入事务的技巧,请告诉我。
2个回答

2
您可以使用工作单元模式来进行事务管理。工作单元模式的主要好处是,您可以将事务策略集中在一个地方,或者在有多个策略时集中在几个地方。最简单的工作单元接口可能是:
public interface IUnitOfWork
{
    void Start();
    void Commit();
    void RollBack();
}

您可以为不同的ORM或存储过程或硬编码SQL创建不同的UnitOfWork实现。您可以在请求开始时启动事务。事务可以在请求结束时被释放。在释放之前,您可以将提交包装在try-catch块中,并在catch中回滚。
try
{
    unitOfWork.Commit();
} 
catch
{
     unitOfWork.RollBack();
     throw;
}

这里介绍了三种事务启动策略:
  • 每个请求:整个请求使用一个事务,在大多数情况下这是最好的方式。
  • 每个方法多次:每个方法使用一个事务。
  • 每个会话:您可以在购物车结账过程的多个请求周围创建一个事务。
您可以使用以下方法来管理您的事务:
  • 属性
  • global.asax 中的 application_begin 和 endrequest 方法
  • httpmodule
当使用 StructureMap 时,您可以在工作单元配置中将混合缓存用作 InstanceScope。您可以使用 StructureMap 将工作单元注入到存储库中。

1
在我目前开发的应用程序中,我的存储库从构造函数中注入的ISessionProvider获取NHibernate的ISession。会话提供程序是AspNetMvcSessionProvider,它将创建一个ISession并在第一次调用ISessionProvider.OpenSession()时开始事务,将ISession存储在当前Web请求中。
在OnActionExecuted中,我手动从容器中提取ISessionProvider,并根据是否抛出异常调用Commit或RollBack - 当然,如果当前未在Web请求中存储任何会话,则不执行任何操作。
这已被证明非常有用,而且我认为它的性能表现相当不错 - 大多数情况下,应用程序仅读取数据,这不会阻塞其他读取事务。我还没有遇到过数据库死锁的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接