Entity framework 每次使用时需要创建/处置的项的依赖项注入

Entity framework 每次使用时需要创建/处置的项的依赖项注入,entity-framework,dependency-injection,inversion-of-control,factory-pattern,Entity Framework,Dependency Injection,Inversion Of Control,Factory Pattern,对于每次使用依赖项时都需要创建/处理的依赖项,处理依赖项的正确方法是什么?也就是说:依赖项只应该在using语句的上下文中使用 public void Foo() { IUnityContainer myContainer = GetContainer(); using (IDataStore store = myContainer.Resolve<IDataStore>()) { //Do work... } } 然后在我的另一节

对于每次使用依赖项时都需要创建/处理的依赖项,处理依赖项的正确方法是什么?也就是说:依赖项只应该在using语句的上下文中使用

public void Foo()
{
    IUnityContainer myContainer = GetContainer();
    using (IDataStore store = myContainer.Resolve<IDataStore>())
    {
        //Do work...
    }
} 
然后在我的另一节课上

public class SomeClass
{
    private IDataStoreFactory factory;

    public SomeClass(IDataStoreFactory factory)
    {
       this.factory = factory;
    }

    public void Foo()
    {
        using (IDataStore store = factory.CreateNew())
        {
           //Do work...
        }
    }
}

这是解决这个问题的有效方法,还是一种不好的做法?我以前没有真正使用过DI(或工厂),所以我想确保我没有做过会让我一蹶不振的事情。

依赖注入本质上是一组与应用程序相关的模式。正如Robert C.Martin在中所解释的:“客户机[…]拥有抽象接口”。这意味着接口是根据客户机的需求定义的,而不是任何特定实现提供的

具体地说,这意味着接口永远不应该派生自
IDisposable
,因为客户端永远不需要它们的依赖关系是可丢弃的;这一关切完全与具体执行有关

这里的要点是,
IDataStore
不应派生自
IDisposable
。相反,它应该只公开客户端需要的方法。让我们调用这样一个方法
Bar

任何客户端都应该能够使用
IDataStore
的任何实现:

var baz = this.store.Bar(qux);
其中,
this.store
IDataStore
的一个实例

那么,你如何处理需要处理的物品呢

你用的是一个。具体来说,您创建了一个
IDataStore
的实现,该实现负责数据库上下文的生命周期管理:

public class DataStoraptor : IDataStore
{
    public IBaz Bar(IQuz qux)
    {
        using (var ctx = MyDbContext())
        {
            return ctx.Bar(qux);
        }
    }
}
这个简化的例子假设
IDataStore
只定义了一个名为
Bar
的成员,但我相信您可以从这个例子中推断出来

该示例的缺点是,它为每个方法调用创建一个新的
MyDbContext
。这是安全的,但可能不是最有效地利用资源。例如,如果在同一线程中有多个客户端使用
IDataStore
,则可能希望能够在该线程中重用
MyDbContext
的单个实例。在这种情况下,您可以使用。然后,您可以以这样一种方式实现该抽象工厂:它返回作用域为特定线程(或其他类型作用域)的实例


不过,这种变化要复杂得多,所以在增加复杂性之前,请确保您需要它。衡量性能,只要性能足够好,就坚持上面所示的简单实现。

在我的例子中,IDataStore有一个方法“GetAll()”返回“IQuerable()”。这使得使用IDataStore的对象可以利用延迟执行。因此,我无法以与“Bar”示例相同的方式处理该对象,因为实际的DbContext在实际执行查询之前会被处理。@NuclearProgrammer-Well。它不公开客户机需要的内容,而是实现提供的内容,这与DIP正好相反。创建IDbContextFactory而不是IDataStoreFactory,并使用基类DbContext而不是IDataStore编写代码是否更好?我需要能够利用延迟执行的优势,同时交换单元测试中数据的来源。@NuclearProgrammer更好的含义是什么?从DIP的角度来看:不,它们都是漏洞百出的抽象。我想我不清楚如何抽象我的DbContext。我想把我的DataContext换成单元测试,并且我需要能够利用延迟执行。
public class DataStoraptor : IDataStore
{
    public IBaz Bar(IQuz qux)
    {
        using (var ctx = MyDbContext())
        {
            return ctx.Bar(qux);
        }
    }
}