【问题标题】:How to get Unit of Work to function with Service Pattern?如何让工作单元与服务模式一起运行?
【发布时间】:2017-06-19 11:46:39
【问题描述】:

我正在使用工作单元模式,正如article 中所述。文章解释说,每个服务都应该注入一个 UnitOfWork:

private readonly IUnitOfWork _unitOfWork;

此外,服务必须有一个公共方法来提交工作单元操作:

public void Save()
{
   _unitOfWork.Commit();
}

Save 方法只能由调用服务的 (webapi) 控制器调用。

但这是我的担忧:

1) 控制器可以通过数据库更新调用多个服务,在这种情况下,它应该为每个服务调用 Save()?如果需要回滚怎么办?

喜欢:

[HttpGet]
public IHttpActionResult UpdateArchive()
{
   _service1.DoUpdate();
   _service1.Save();
   _service2.DoUpdate();
   _service2.Save();
}

如果 service2.Save 失败怎么办?

2)如果一个服务调用另一个服务,控制器如何知道调用哪个Save?

我对这个工作单元有点困惑。

【问题讨论】:

    标签: c# asp.net entity-framework repository-pattern


    【解决方案1】:

    在这种情况下,它应该为每个服务调用 Save()

    这取决于服务是否共享相同的工作单元。如果是,请在其中任何一个上调用 Save,它将操作委托给同一个 UoW。

    如果需要回滚怎么办

    既然没有事务,你应该如何回滚任何东西?

    另一方面,在编排上引入显式事务使得回滚更改变得微不足道:

    try
    {
      using ( TransactionScope scope = new TransactionScope() )
      {
         _service1.DoUpdate();
         _service1.Save();
         _service2.DoUpdate();
         _service2.Save();
    
         scope.Complete();
      }
    }
    catch
    {
       // rollback occurs since the transaction was not completed
    }
    

    TransactionScope 非常方便,因为它可以正确处理共享 UoW 上的事务和注入不同服务的多个不同 UoW 上的事务。

    如果 service2.Save 失败怎么办?

    你回滚事务,这里几乎没有其他选择。

    无论如何,repositories/uow over EF are disputable。您的部分问题是多个服务共享同一个 UoW 实例,所以基本上您调用哪个 Save 并不重要,它们都在同一个 DbContext 上调用 SaveChanges

    我的意见(即使这里应该避免意见)是您可能会从您的服务中删除Saves,并在编排结束时在您的数据库上下文中坚持使用单个SaveChanges。这将使意图更加清晰 - 服务将更改 UoW 的内部状态,但保持更改的责任在控制器上。

    【讨论】:

    • 关于您的最后一段:您不会直接从控制器调用数据库上下文中的 SaveChanges,对吗?我的意思是,不应该把它抽象掉吗?
    • 这真的取决于我手头是否有 DbContext。如果不是(例如,它是由 DI 容器注入的,您甚至在控制器中的任何地方都看不到它)我会在其中一项服务上调用 Save
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多