Общий репозиторий фабрики и сервисный состав - PullRequest
0 голосов
/ 27 апреля 2011

В предыдущий вопрос люди помогли мне решить проблему времени жизни репозитория, теперь возникает вопрос, как сделать так, чтобы он хорошо работал в композитном сервисе.

Допустим, у меня есть сервисы:

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 временный (потому что вы получите два разных данных, и этотребовать включения распределенных транзакций, чего мы стараемся избегать).Любые иды, как правильно написать это?

Ответы [ 2 ]

1 голос
/ 17 апреля 2012

IMO - это сценарий распределенной транзакции.

В примере, который вы упомянули, OrderService & ReservationService использует тот же контекст данных - деталь реализации, скрытая в коде.

Я не думаю, что правильно передавать эти знания до CompositionService, заключая вызовы сервиса в TransactionScope, так как теперь сервис композиции знает о контексте общих данных и поэтому должен использовать 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?)

В этом случае детали реализации сервисов полностью скрыты от потребителя сервиса, в то время как составление также возможно, независимо от базовой детализации реализации.

НТН.

1 голос
/ 27 апреля 2011

Мои наблюдения:

  1. В общем, фабрики должны быть одиночными.Если ваша фабрика не синглтон, то вы, вероятно, просто прячете за ней другую фабрику.
  2. Фабрики предназначены для создания объектов по требованию .Ваш код просто создает хранилище в конструкторе, поэтому я не вижу особой разницы между этим и простым превращением хранилища в параметр прямого внедрения в конструкторе.

Все это мне кажетсяОбходные пути вокруг более фундаментальной проблемы (описанной в вашем первом вопросе), и эти обходные пути только усложняют проблему.Если вы не решите корневую проблему, вы получите сложную схему зависимостей и вонючий код.

...