Ninject ActivationBlock как единица работы - PullRequest
2 голосов
/ 29 декабря 2011

У меня есть приложение WPF с MVVM.Предполагая, что композиция объекта из ViewModel вниз выглядит следующим образом:

MainViewModel
    OrderManager
        OrderRepository
            EFContext
        AnotherRepository
            EFContext
    UserManager
        UserRepository
            EFContext

Мой оригинальный подход заключался в том, чтобы вводить зависимости (из ViewModelLocator) в мою модель представления, используя .InCallScope () для EFContext и .InTransientScope () длявсе остальное.Это приводит к возможности выполнения «бизнес-транзакции» для нескольких объектов бизнес-уровня (менеджеров), которые в конечном итоге совместно используют один и тот же контекст Entity Framework.Я бы просто сказал, что Commit () сказал контекст в конце для сценария типа Unit of Work.

Это работало как задумано, пока я не понял, что я не хочу долгоживущих контекстов Entity Framework на уровне View Model, данныхпроблемы целостности при множестве описанных операций ЗДЕСЬ .Я хочу сделать что-то похожее на мои веб-проекты, где я использую .InRequestScope () для моего контекста Entity Framework.В моем настольном приложении я определю единицу работы, которая будет служить бизнес-транзакцией, если вы захотите, как правило, она будет заключать все в нажатие кнопки или подобное событие / команду.Кажется, что использование ActivationBlock Ninject может сделать это для меня.

internal static class Global
{
    public static ActivationBlock GetNinjectUoW()
    {            
        //assume that NinjectSingleton is a static reference to the kernel configured with the necessary modules/bindings
        return new ActivationBlock(NinjectSingleton.Instance.Kernel);
    }   
}

В моем коде я намерен использовать его следующим образом:

//Inside a method that is raised by a WPF Button Command ...
using (ActivationBlock uow = Global.GetNinjectUoW())
{
    OrderManager orderManager = uow.Get<OrderManager>();
    UserManager userManager = uow.Get<UserManager>();

    Order order = orderManager.GetById(1);
    UserManager.AddOrder(order);
    ....
    UserManager.SaveChanges();
}

Вопросы:

  1. Мне кажется, что это похоже на то, как я веду бизнес в сети, есть ли что-то изначально неправильное в этом подходе, который я пропустил?
  2. Правильно ли я понимаю, что все вызовы .Get <> вызывают с использованиемблок активации будет производить "синглтоны" локально для этого блока?Я имею в виду, что сколько бы раз я ни просил OrderManager, он всегда будет давать мне один и тот же в пределах блока.Если OrderManager и UserManager составляют один и тот же репозиторий (скажем, SpecialRepository), оба они будут указывать на один и тот же экземпляр репозитория, и, очевидно, все репозитории под ним совместно используют один и тот же экземпляр контекста Entity Framework.

Ответы [ 2 ]

2 голосов
/ 29 декабря 2011

На оба вопроса можно ответить да:

  1. Да - это местоположение службы, которое вы не должны делать
  2. Да, вы правильно понимаете
1 голос
/ 31 июля 2015

Правильный объем единицы работы, реализованный в Ninject.Extensions.UnitOfWork , решает эту проблему.

Установка:

_kernel.Bind<IService>().To<Service>().InUnitOfWorkScope();

Использование:

using(UnitOfWorkScope.Create()){
    // resolves, async/await, manual TPL ops, etc    
}
...