1

在实现MVC项目时,我通常添加服务层来执行实际工作。但实际上有时候1个Web请求应该用几个AppService方法来完成。然后,工作单元(UoW)的位置可能会影响编码处理。不管在C#EF/Java Spring中,服务层方法中都有事务注释,所以事务是基于每个服务的(即服务层上的UoW)。让我们的Java版本为例这里:在服务层而不是控制器上应用工作单元的好处

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED) 
Public class UserAppService{ 
    public UserDTO createUser() { 
     // Do sth to create a new user 
     userRepository.save(userBean); 

     // Convert userBean to userDTO 
     return userDTO; 
    } 
    public xxx DoSth() { 
     // Break the operation here 
     throw new Exception("Whatever"); 

     // (never execute actually) 
     sthRepository.save(someBean); 
    } 
} 

然后在控制器:

Public class SomeController : Controller { 
    Public xxx DoSth(){ 
    UserAppService Service = new UserAppService(); 
    Service.CreateUser(); // DB committed 
    Service.DoSth();  //Exception thrown 

    } 
} 

通过这种结构,如果有扔在2号服务方法调用的任何异常,第一服务方法还承诺用户DB。如果我想要“全有或全无”处理,除非将这些服务方法调用包装为另一个包含单事务的包装服务调用,否则此结构不起作用。但这是额外的工作。

另一个版本是在Controller动作级别上使用事务(即Controller Action上的UoW)。我们以C#代码为例:

备注:此处的代码版本2中的AppService使用控制器中定义的DbContext(类似于事务),并且不会在内部进行任何提交。

Public class SomeController : Controller { 
    Public ActionResult DoSth(){ 
    using (var DB = new DbContext()){ 
     Var UserAppService = new UserAppService(DB); 
     var userEntity = userAppService.GetUser(userId); 
     UserAppService.DoSth(userEntity); 

     Var AnotherAppService = new AnotherAppService(DB); 
     AnotherAppService.DoSthElse(userEntity); 

     // Throw exception here 
     throw new Exception("Whatever"); 

     DB.Save(); // commit 
    } 
    } 
} 

在这个例子中,将不会有局部提交到DB。

在服务层上应用UoW真的更好吗?

回答

1

这是更好的,因为你遵循面向对象编程的主要原则关注的问题。如果你做了另一个控制器,并希望使用相同的对象做更多的数据库处理?你不想实例化控制器,在其中完成不同的事情。顺便检查一下门面服务模式http://soapatterns.org/design_patterns/service_facade它可以帮助你理解它为什么如此性感。 enter image description here。上面的图片显示了这种模式,基本上你用数据库访问对象在服务层上包含事务,因此customerService对象可以包装1,2 ... inf事务,并且全部失败或成功。

+0

如果遵循UoW on Service模式,给定一个常见的情况:1个HTTP POST调用(即1个控制器动作)需要在带有数据库更改的2+服务方法上完成,如何防止“部分提交”而不会破坏UoW on Service模式? –

+0

嗨,检查我的更新答案 – Javasharp

1

在服务层上应用UoW真的更好吗?

国际海事组织编号你刚刚找出原因。如果服务方法谨慎且可重用,则它们也不适合进行原子事务处理。

在.NET中,控制器应控制事务生命周期,并在事务中使用服务方法。

请注意,此意味着服务方法应该是本地方法调用,而不是远程或Web服务调用。

相关问题