Unity框架 - 在适当的时间创建和部署Entity Framework datacontexts

Tob*_*ans 6 .net inversion-of-control unity-container

有了StackOverflow的一些帮助,我有Unity Framework来创建我的链接依赖项,包括一个Entity Framework 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>();
Run Code Online (Sandbox Code Playgroud)

这非常适合创建我的Presenter对象并显示相关视图,我真的很高兴.

但是,我现在遇到的问题是创建和处理Entity Framework对象的时间(我怀疑这将适用于任何IDisposable对象).像这样使用Unity,SQL EF对象"CommunergySQLiteEntities"是立即创建的,因为我已将其接口IUnitOfWork添加到MeterPresenter的构造函数中

    public MeterPresenter(IMeterView view, IUnitOfWork unitOfWork, IRepositoryFactory cacheRepository)
    {
        this.mView = view;
        this.unitOfWork = unitOfWork;
        this.cacheRepository = cacheRepository;
        this.Initialize();
    }
Run Code Online (Sandbox Code Playgroud)

我当时对此感到有点不安,因为我不想保持打开数据库连接,但我看不到使用Unity依赖注入的任何其他方式.果然,当我实际尝试使用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}
Run Code Online (Sandbox Code Playgroud)

我对IoC原理的理解是,您将所有依赖项设置在顶部,解决您的对象并远离您.但是,在这种情况下,某些子对象(例如datacontext)不需要在创建父Presenter对象时初始化(就像在构造函数中传递它们一样),但是Presenter确实需要了解IUnitOfWork在与数据库通信时使用的类型.

理想情况下,我想在我解决的Presenter中找到这样的东西:

using(IUnitOfWork unitOfWork = new NewInstanceInjectedUnitOfWorkType())
{
    //do unitOfWork stuff
}
Run Code Online (Sandbox Code Playgroud)

因此,Presenter知道IUnitOfWork实现用于直接创建和处理的内容,最好是从原始的RegisterType调用.我是否必须在我的Presenter中放置另一个Unity容器,否则可能会产生新的依赖关系?

对于IoC大师来说,这可能是非常明显的,但我真的很欣赏指向正确方向的指针.

Aar*_*ght 4

您无需担心在ObjectContext创建演示者的同时初始化 an - anObjectContext不会保持打开的数据库连接。相反,当它实际需要与数据库通信时,即当您执行查询或提交更改时,它会根据需要打开连接,并在完成后立即关闭连接。仅当您显式打开连接时,它才会保持连接打开,这在实体框架中很少见。

如果您收到ObjectDisposedExceptionusing ,ContainerControlledLifetimeManager则意味着您的容器在演示者之前被处置,这是一个设计错误。目前尚不完全清楚您的环境是什么(ASP.NET?Winforms?),但ContainerControlledLifetimeManager这里可能不合适,因为它作为 Singleton 实例工作。通常,当您解析类型时,您实际上会想要创建一个新的上下文实例 - 如果您使用单例,则会遇到许多问题。

所以 - 我会摆脱这里ContainerControlledLifetimeManager,并确保你的容器不会过早被处置;它位于一个块中的事实using表明这可能是您的ObjectDisposedException. (当然,您最终仍然需要处置容器 - 只是您可能正在做一些类似创建无模式表单之类的事情,该表单在控制离开范围后很长时间仍保持活动状态using)。