通用存储库工厂和服务组合

本文关键字:服务 服务组 组合 工厂 存储 | 更新日期: 2023-09-27 17:53:28

在之前的问题中,人们帮助我解决了存储库生命周期问题,现在的问题是如何使它在组合服务中很好地工作。

假设我有services:

public class OrderService : IOrderService 
{         
     IRepository<Order> orderRepository;          
     public OrderService(IRepositoryFactory repositoryFactory) 
     {
        orderRepository = repositoryFactory.GetRepository<Order>();
     }
     public void CreateOrder(OrderData orderData) 
     {
        ...
        orderRepository.SubmitChanges();
     }
}
public class ReservationService : IReservationService 
{
     IRepository<Reservation> reservationRepository;
     public ReservationService(IRepositoryFactory repositoryFactory) 
     {
        reservationRepository = repositoryFactory.GetRepository<Reservation>();
     }
     public void MakeReservations(OrderData orderData)   
     {
         ...
         reservationService.SubmitChanges();
     }
}

现在是有趣的部分——组合服务:

public class CompositionService : ICompositionService {
     IOrderService orderService;
     IReservationService reservationService;
     public CompositionService(IOrderService orderService, IReservationService reservationService) 
     {
        this.orderService = orderService;
        this.reservationService = reservationService;
     }
     public void CreateOrderAndMakeReservations(OrderData orderData) 
     {
        using (var ts = new TransactionScope()) 
        {
           orderService.CreateOrder(orderData);
           reservationService.MakeReservations(orderData);
           ts.Complete();
        }
     }
}

问题是,如果IRepositoryFactory生活方式是暂时的,它将无法正确工作(因为您将获得两个不同的数据上下文,这将需要启用分布式事务,这是我们试图避免的)。有什么办法正确地写这个吗?

通用存储库工厂和服务组合

我的观察:

    一般来说,工厂应该是单例的。如果您的工厂不是单例的,那么您可能只是在它后面隐藏了另一个工厂。
  1. 工厂用于按需创建对象。你的代码只是在构造函数中创建了一个存储库,所以我真的看不出这和在构造函数中简单地将存储库作为直接注入参数有什么区别。

在我看来,这些都像是一个更基本问题的变通方法(在你的第一个问题中描述),这些变通方法只会使问题更加复杂。除非你解决了根本问题,否则你最终会得到一个复杂的依赖模式和一段难闻的代码。

IMO -这是一个分布式事务场景。

在你提到的例子中,OrderService &ReservationService使用相同的数据上下文是隐藏在代码中的实现细节。

我认为通过在TransactionScope中包装服务调用将此知识传递给CompositionService是不正确的,因为现在组合服务知道共享数据上下文&so需要使用TransactionScope来正确运行代码。

在我看来,组合服务代码应该是这样的:
try{
 if(orderService.TryCreateOrder(orderData)){
   if(reservationService.TryMakeReservation(orderData)){
      reservationService.Commit();
      orderService.Commit();
   }
   else{
     orderService.TryRollbackOrder(orderData);
     throw new ReservationCouldNotBeMadeException();
   }
 }
 else{
  throw new OrderCouldNotBeCreatedException();
 }
}
catch(CouldNotRollbackOrderServiceException){
 // do something here...
}
catch(CouldNotCommitServiceException){
 // do something here...
}

在本例中,OrderService。TryCreateOrder方法将插入一个带有PendingReservation状态的订单或其他一些相关状态,这些状态表明该订单已插入,但尚未完成。此状态将在服务上调用提交时更改(UnitOfWork模式?)

在这种情况下,服务的实现细节对服务的消费者是完全隐藏的,而组合也是可能的,独立于底层的实现细节。

HTH .