什么时候提交NHibernate Transaction?

Mat*_*ell 1 nhibernate asp.net-mvc dependency-injection transactions

虽然对Webforms和Linq非常熟悉,但我是ASP.NET MVC和NHibernate World的新手.我一直在使用Bob Cravens的例子来完成一个项目.我的应用程序主要是读取和非顺序写入,因此通常我不会使用事务.但是为了实现工作单元模式,包括Ayende博客在内所有研究都说我应该这样做.

我遇到的问题是 -

  • Ninject创建会话并打开交易.
  • Ninject将存储库注入服务,将服务注入控制器.
  • 我对对象的属性和子进行了一些更改并保存在聚合根上.这会调用Transaction.Commit(正常工作,如预期的那样)
  • 在稍后在控制器中的另一种方法中,我尝试保存单独的对象
  • 第二次调用失败,因为事务不再处于活动状态.

我正在考虑向UnitOfWork添加一个bool"CommitNeeded",它将由我的Save()方法设置并有条件地触发UnitOfWork.Dispose()上的Commit().这是一个好主意吗?

我应该删除交易基础设施吗?我应该将Commit()改为Flush()吗?

任何有助于修复我的反模式的建议都将受到赞赏.


在回应评论时 - 我想我不介意它们是一起发生还是分开发生.有两件事情在发生.第一个更改"客户"对象,然后保存它.第二个创建一个日志记录条目,然后调用相同的"保存"方法.

var Customer = ServiceLayer.GetCustomer(...);
Transmogrify(Customer, Customer.Children, Widgets, ...);
ServiceLayer.Save(Customer)

ServiceLayer.RecordEvent(Customer, "Customer was frobbed")
Run Code Online (Sandbox Code Playgroud)

LogEvent的样子

public void RecordEvent(Customer customer, int eventTypeId, string description)
{
    ...

    Save(customer);
}
Run Code Online (Sandbox Code Playgroud)

RecordEvent方法有自己的"保存",因为它是从没有数据更改的其他控制器调用的.我相信保存电话不属于这两个地方.问题是,在哪里?服务层的Dispose()方法?或像其他用户建议的过滤器?

Mik*_*nty 5

使用ASP.NET MVC,我使用动作过滤器将事务范围绑定到控制器操作执行生命周期.这在大多数情况下都很有效,但是你必须小心谨慎,不要让交易开放太久.

public class UnitOfWorkActionFilter : ActionFilterAttribute
{
    public IUnitOfWork UnitOfWork { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        UnitOfWork.Start();
        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Exception == null)
        {
            UnitOfWork.Commit();
        }
        else
        {
            UnitOfWork.Rollback();
        }
        UnitOfWork.Dispose();
        base.OnActionExecuted(filterContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的情况下,我通过自定义使用属性注入ControllerActionInvoker来获取IUnitOfWork依赖项ActionFilterAttribute.