Платформа единицы - создание и реализующая компания Платформа datacontexts в подходящее время

С некоторой доброжелательной справкой от StackOverflow у меня есть Платформа Единицы для создания моих цепочечных зависимостей, включая Платформу Объекта datacontext объект:

using (IUnityContainer container = new UnityContainer())
{
    container.RegisterType<IMeterView, Meter>();
    container.RegisterType<IUnitOfWork, CommunergySQLiteEntities>(new ContainerControlledLifetimeManager());
    container.RegisterType<IRepositoryFactory, SQLiteRepositoryFactory>();
    container.RegisterType<IRepositoryFactory, WCFRepositoryFactory>("Uploader");
    container.Configure<InjectedMembers>()
        .ConfigureInjectionFor<CommunergySQLiteEntities>(
            new InjectionConstructor(connectionString));

    MeterPresenter meterPresenter = container.Resolve<MeterPresenter>();

это работает действительно хорошо в создании моего объекта Предъявителя и отображении связанного представления, я действительно рад.

Однако проблема, с которой я сталкиваюсь теперь, по синхронизации создания и избавления от объекта Платформы Объекта (и я подозреваю, что это пойдет для любого объекта IDisposable). Используя Единицу как это, EF SQL возражают, что "CommunergySQLiteEntities" немедленно создается, поскольку я добавил его интерфейс, IUnitOfWork конструктору MeterPresenter

    public MeterPresenter(IMeterView view, IUnitOfWork unitOfWork, IRepositoryFactory cacheRepository)
    {
        this.mView = view;
        this.unitOfWork = unitOfWork;
        this.cacheRepository = cacheRepository;
        this.Initialize();
    }

Я чувствовал себя немного беспокоящимся об этом в то время, поскольку я не хочу держать открытый соединение с базой данных, но я не мог видеть никакой другой способ использовать внедрение зависимости Единицы. Конечно же, когда я на самом деле пытаюсь использовать datacontext, я получаю эту ошибку:

    ((System.Data.Objects.ObjectContext)(unitOfWork)).Connection 
  '((System.Data.Objects.ObjectContext)(unitOfWork)).Connection'
threw an exception of type 'System.ObjectDisposedException'
 System.Data.Common.DbConnection {System.ObjectDisposedException}

Мое понимание принципа МОК - то, что Вы настраиваете все свои зависимости наверху, разрешаете Ваш объект, и далеко Вы идете. Однако в этом случае некоторые дочерние объекты, например, datacontext, не должны быть инициализированы в то время, когда родительский объект Предъявителя создается (как Вы были бы путем передачи их в конструкторе), но Предъявитель действительно должен знать о том, какой тип использовать для IUnitOfWork, когда он хочет говорить с базой данных.

Идеально, я хочу что-то вроде этого в своем разрешенном Предъявителе:

using(IUnitOfWork unitOfWork = new NewInstanceInjectedUnitOfWorkType())
{
    //do unitOfWork stuff
}

Таким образом, Предъявитель знает, какую реализацию IUnitOfWork использовать, чтобы создать и немедленно избавиться, предпочтительно от исходного RegisterType называют. Я должен поместить другой контейнер Единицы в своем Предъявителе, рискуя тем, чтобы создать новую зависимость?

Это, вероятно, действительно очевидно для гуру МОК, но я был бы очень признателен за указатель в правильном направлении.

6
задан julealgon 28 February 2014 в 15:54
поделиться

2 ответа

Вам не нужно беспокоиться об инициализации ObjectContext одновременно с созданием презентатора - ObjectContext не удерживает открытое соединение с базой данных. Скорее, он открывает соединения по мере необходимости, когда ему действительно нужно поговорить с базой данных, то есть когда вы выполняете запрос или фиксируете изменения, и снова закрывает соединение, как только оно завершается. Он будет удерживать соединение открытым только в том случае, если вы его явно откроете, что редко бывает с Entity Framework.

Если вы получаете исключение ObjectDisposedException с помощью ContainerControlledLifetimeManager , это означает, что ваш контейнер удаляется раньше ведущего, что является ошибкой проектирования. Не совсем понятно, что это за среда (ASP.NET? Winforms?), Но ContainerControlledLifetimeManager , вероятно, здесь не подходит, поскольку он работает как экземпляр Singleton. Обычно вы действительно хотите создать новый экземпляр контекста при разрешении типа - есть много проблем, с которыми вы можете столкнуться, если вместо этого используете синглтон.

Итак - я бы избавился от ContainerControlledLifetimeManager здесь, а также удостоверился, что ваш контейнер не утилизируется слишком рано; тот факт, что он находится в блоке using , указывает на то, что это, вероятно, причина вашего ObjectDisposedException . (Конечно, вам все равно нужно избавиться от контейнера - просто вы, вероятно, делаете что-то вроде создания немодальной формы, которая остается активной еще долго после того, как элемент управления покидает с использованием области ).

4
ответ дан 17 December 2019 в 04:45
поделиться

Почему бы вам просто не удалить IUnitOfWork из конструктора и вместо этого не внедрить контейнер единства? Таким образом, у вас будет возможность гибко вызывать container.Resolve() в любом месте вашего кода, когда это необходимо.

Пример:

using(IUnitOfWork unitOfWork = container.Resolve<IUnitOfWork>()) 
{ 
    //do unitOfWork stuff 
} 

Не забудьте установить время жизни экземпляра на single.

Michael

1
ответ дан 17 December 2019 в 04:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: