通用存储库工厂和服务组合
在上一个问题中,人们帮助我解决了存储库生命周期问题,现在有一个问题如何让它在组合服务中很好地工作。
假设我有服务:
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 生活方式是瞬态的,它将无法正常工作(因为您将获得两个不同的数据上下文,并且需要启用分布式事务,我们需要启用分布式事务)尽量避免)。有什么想法如何正确写这个吗?
In previous question folks helped me to solve repository lifetime problem, now there's a question how to make it work nicely in composite service.
let's say i have 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();
}
}
And now the intersting part - composition service:
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();
}
}
}
Problem is, that it won't work correctly if IRepositoryFactory lifestyle is transient (because you would get two different datacontexts and that would require distributed transactions to be enabled, which we try to avoid). Any ides how to write this correctly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我的观察:
在我看来,这些都是围绕更基本问题(在第一个问题中描述)的解决方法,而这些解决方法只会使问题变得更加复杂。除非你解决根本问题,否则你最终会得到一个复杂的依赖模式和臭代码。
My observations:
These all seem to me like a workarounds around a more fundamental problem (described in your first question) and these workarounds only make the problem more complicated. Unless you solve the root problem you will end up with a complex dependency schema and a smelly code.
IMO - 这是一个分布式事务场景。
在您提到的示例中,
OrderService
&ReservationService
使用相同的数据上下文是隐藏在代码中的实现细节。我认为通过将服务调用包装在 TransactionScope 中来将这些知识传递给 CompositionService 是不正确的,因为现在组合服务知道共享数据上下文和数据。因此需要使用 TransactionScope 才能正确运行代码。
在我看来,组合服务代码应该如下所示:
在这种情况下,OrderService.TryCreateOrder 方法将插入一个具有 PendingReservation 状态或其他相关状态的订单,该状态指示订单已插入,但尚未完成。这种状态将在服务上调用提交时发生变化(UnitOfWork 模式?)
在这种情况下,服务的实现细节对服务的使用者完全隐藏,而组合也是可能的,独立于底层实现细节。
HTH。
IMO - this is a Distributed Transaction scenario.
In the example you mentioned,
OrderService
&ReservationService
use the same data context is an implementation detail hidden in the code.I don't think it is correct to pass this knowledge up to the
CompositionService
by wrapping the service calls in a TransactionScope as now the composition service is aware of the shared data context & so needs to use a TransactionScope to run the code correctly.In my opinion, the composition service code should look like:
In this case, the OrderService.TryCreateOrder method will insert an Order with a PendingReservation status or some other relevant status which indicates that the Order is inserted, but not completed. This state will change on the commits are called on the services (UnitOfWork pattern?)
In this case, the implementation details of the services are completely hidden from the consumer of the service, while composition is also possible, independent on the underlying implementation detail.
HTH.