С некоторой доброжелательной справкой от 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 называют. Я должен поместить другой контейнер Единицы в своем Предъявителе, рискуя тем, чтобы создать новую зависимость?
Это, вероятно, действительно очевидно для гуру МОК, но я был бы очень признателен за указатель в правильном направлении.
Вам не нужно беспокоиться об инициализации ObjectContext
одновременно с созданием презентатора - ObjectContext
не удерживает открытое соединение с базой данных. Скорее, он открывает соединения по мере необходимости, когда ему действительно нужно поговорить с базой данных, то есть когда вы выполняете запрос или фиксируете изменения, и снова закрывает соединение, как только оно завершается. Он будет удерживать соединение открытым только в том случае, если вы его явно откроете, что редко бывает с Entity Framework.
Если вы получаете исключение ObjectDisposedException
с помощью ContainerControlledLifetimeManager
, это означает, что ваш контейнер удаляется раньше ведущего, что является ошибкой проектирования. Не совсем понятно, что это за среда (ASP.NET? Winforms?), Но ContainerControlledLifetimeManager
, вероятно, здесь не подходит, поскольку он работает как экземпляр Singleton. Обычно вы действительно хотите создать новый экземпляр контекста при разрешении типа - есть много проблем, с которыми вы можете столкнуться, если вместо этого используете синглтон.
Итак - я бы избавился от ContainerControlledLifetimeManager
здесь, а также удостоверился, что ваш контейнер не утилизируется слишком рано; тот факт, что он находится в блоке using
, указывает на то, что это, вероятно, причина вашего ObjectDisposedException
. (Конечно, вам все равно нужно избавиться от контейнера - просто вы, вероятно, делаете что-то вроде создания немодальной формы, которая остается активной еще долго после того, как элемент управления покидает с использованием области
).
Почему бы вам просто не удалить IUnitOfWork из конструктора и вместо этого не внедрить контейнер единства? Таким образом, у вас будет возможность гибко вызывать container.Resolve
в любом месте вашего кода, когда это необходимо.
Пример:
using(IUnitOfWork unitOfWork = container.Resolve<IUnitOfWork>())
{
//do unitOfWork stuff
}
Не забудьте установить время жизни экземпляра на single.
Michael