在previous question人帮助我解决了存储库生存期问题,现在有一个问题是如何使它在复合服务中很好地工作。
假设我有服务:
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生活方式是暂时的(因为您将获得两个不同的datacontexts并且需要启用分布式事务,我们会尽量避免),它将无法正常工作。任何想法如何正确写这个?
答案 0 :(得分:1)
我的观察:
在我看来,这些都是围绕更基本问题的解决方法(在您的第一个问题中描述),这些解决方法只会使问题更加复杂。除非你解决根问题,否则你最终会得到一个复杂的依赖模式和一个有臭味的代码。
答案 1 :(得分:1)
IMO - 这是一个分布式事务方案。
在您提到的示例中,OrderService
&amp; ReservationService
使用相同的数据上下文是隐藏在代码中的实现细节。
我认为通过在TransactionScope中包装服务调用将此知识传递给CompositionService
是不正确的,因为现在组合服务已知道共享数据上下文&amp;所以需要使用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。