我对在我的MVC应用程序中编写以下代码感到恼火。
using(var tx = new TransactionScope()){
blah...
tx.Complete()
}
我想以某种方式制作这款DRYer。
我想到了几个不同的选择。
这些都是好主意吗?我应该注意的任何问题?第二个选项似乎可能是一个很好的方法来解决许多僵局。
哦是的,我也在使用StructureMap和一个自定义控制器工厂将deps注入我的控制器,以防有人知道一些注入事务的技巧。
答案 0 :(得分:2)
您可以使用Unit of Work pattern进行交易管理。工作单元模式的主要好处是,当您有多种策略时,您可以将交易策略保留在一个地方或几个地方。 最简单的工作单元界面可以是:
public interface IUnitOfWork
{
void Start();
void Commit();
void RollBack();
}
您可以为不同的ORM或存储过程或硬编码的sql创建各种UnitOfWork实现。您可以在请求开始时启动事务。交易可以在请求结束时处理。在处理之前,您可以将提交包装在try-catch块中,并在catch中进行回滚。
try
{
unitOfWork.Commit();
}
catch
{
unitOfWork.RollBack();
throw;
}
交易启动策略是:
您可以使用以下方式管理交易:
使用StructureMap时,可以在工作单元配置中将混合缓存用作InstanceScope。您可以使用StructureMap将工作单元注入存储库。
答案 1 :(得分:1)
在我正在开发的应用程序中,我的存储库从构造函数中注入的ISession
获取NHibernate ISessionProvider
。会话提供程序是AspNetMvcSessionProvider
,它将创建ISession
并在第一次调用ISessionProvider.OpenSession()
时开始事务,将ISession
存储在当前Web请求中。
在OnActionExecuted
中,我手动将ISessionProvider
从我的容器中拉出来,并在其上调用Commit
或RollBack
,具体取决于是否抛出异常 - 不执行任何操作当然,如果Web请求中当前没有存储会话。
这已被证明是有用的,我认为它表现得非常好 - 大部分时间,应用程序只是读取数据,这不会阻止其他阅读事务。我还没有遇到数据库死锁。