4

各リポジトリメソッド内に作業単位を作成するUnitOfWorkFactoryを持つコードを継承しました。問題は、単一のリポジトリメソッドが完全な作業単位になることはめったにないため、何か問題が発生した場合、OrderService.PlaceOrderその作業単位は1つの単位ではないため、ロールバック/破棄できないことです。

コードを見ると、作業単位をサービスクラスまたはプレゼンターのいずれかに移動する必要があると思います。私が抱えている問題は、それをサービスまたはリポジトリに渡す方法です。プレゼンターにはサービスのインスタンスが渡され、サービスにはリポジトリのインスタンスが渡されます。

作業単位を作成して、サービス、リポジトリー、およびプレゼンターのコンストラクターを注入することはできますが、それでは単一の作業単位を超えて生きることになります。これはデスクトップアプリであるため、プレゼンターとそれが渡すすべてのサービスは、複数の作業単位で存続できます。

作業単位を渡すことができると私が考える唯一の方法は、それをすべてのサービス/リポジトリメソッドにパラメータとして追加することです。それよりも良い方法があるはずだと思わずにはいられませんが、何かが足りないのでしょうか。

コードは次のようになります。

リポジトリ:

class OrderRepository
{
    public UnitOfWorkFactory UnitOfWorkFactory;

    public OrderRepository(UnitOfWorkFactory unitOfWorkFactory)
    {
        UnitOfWorkFactory = unitOfWorkFactory;
    }

    public void Save(Order order)
    {
        using(var uow = UnitOfWorkFactory.Create())
        {
            // save order
            uow.commit();
        }
    }
}

サービス:

class OrderService
{
    protected IOrderRepository OrderRepository;
    protected IProductService ProductService;

    public OrderService(IOrderRepository orderRepository, IProductRepository productService)
    {
        OrderRepository = orderRepository;
        ProductService = productService;
    }

    public void PlaceOrder(Order order)
    {
        foreach(var item in order.Items)
        {
            if(!ProductService.IsInstock(item.Product, item.Quantity))
                throw new ProductOutOfStockException(product);

            ProductService.MarkForDispatch(item.Product, item.Quantity);
        }

        OrderRepository.Save(order);
    }

    public void CancelOrder(Order order)
    {
        ProductService.UnmarkForDispatch(item.Product, item.Quantity);

        order.IsCanceled = true;
        OrderRepository.Save(order);
    }
}

プレゼンター:

class OrderPresenter
{
    protected IOrderView OrderView;
    protected IOrderService OrderService;

    public OrderPresenter(IOrderView orderView, IOrderService orderService)
    {
        OrderView = orderView;
        OrderService = orderService;
    }

    public void PlaceOrder()
    {
        OrderService.PlaceOrder(order);
    }

    public void CanelOrder()
    {
        OrderService.CancelOrder(order);
    }
}
4

2 に答える 2

2

これについては簡単な答えはありません。あなたは私がこの非常に主題について以前に書いたこのブログ投稿で完全な答えをチェックすることができます。[Yet Another UoW、リポジトリ記事]
(記事を読んだらどう思うか教えてください)

于 2013-02-26T23:19:56.990 に答える
2

最終的には工場を利用して、その作業単位を渡すことにしました。次に、ファクトリは渡されたUOWを使用して他のすべてを作成します。

これは、最終的に次のことを行った場合にどうなりますか。

リポジトリ:

public class Repository : IRepoository
{
    IUnitOfWork UnitOfWork;

    public Repository(IUnitOfWork uow)
    {
        UnitOfWork = uow;
    }

    public void SomeOtherMethod(int id)
    {
        // Do something
    }
}

サービス:

public class Service : IService
{
    IUnitOfWork UnitOfWork;
    IRepoository Repository;

    public Service(IUnitOfWork uow, IRepoository repository)
    {
        UnitOfWork = uow;
        Repository = repository;
    }

    public void SomeMethod(int id)
    {
        Repository.SomeOtherMethod(id);
        // do other stuff
    }
}

工場:

public class IUnitOfWorkFactory
{
    IUnitOfWork Create();
}

public class IServiceFactory
{
    IService Create(IUnitOfWork uow);
}

このIServiceFactory.Createメソッドは、サービスとサービスが依存するリポジトリの両方を作成し、渡された作業単位の両方を提供します。

プリセッタ:

public class Presenter
{
    protected UnitOfWorkFactory UnitOfWorkFactory;
    protected IServiceFactory ServiceFactory;

    public Presenter(IUnitOfWorkFactory unitOfWorkFactory, IServiceFactory serviceFactory)
    {
        UnitOfWorkFactory = unitOfWorkFactory;
        ServiceFactory = serviceFactory;
    }

    public void DoSomething()
    {
        // Get a new UOW from the factory
        using(var uow = unitOfWorkFactory.Create())
        {
            // Then create the service and repository with the new UOW via the ServiceFactory
            var service = serviceFactory.Create(uow);
            service.SomeMethod(20);

            uow.Commit();
        }
    }
}
于 2013-03-02T19:59:54.153 に答える