2

阅读了Mark Seemann 的博客文章以及引用它的响应后,我理解了使用服务定位器模式而不是通过类构造函数进行依赖注入的缺点。我还阅读了这个Dependency Injection with Ninject, MVC 3 和使用服务定位器模式,它也讨论了这个问题。

但是,我的问题涉及这种特殊情况:

public class MyController
{
    public void GetData()
    {
        using (var repository = new Repository())
        {
            // Use the repository which disposes of an Entity Framework
            // data context at the end of its life.
        }
    }

    // Lots of other methods.
}

在这里,我有一个控制器,其中包含一个调用存储库的方法,该存储库自动实例化内部实体框架数据上下文。使用这个单一数据上下文,因为该上下文被存储库中的每个方法调用,因此在存储库对象的整个生命周期共享单个上下文似乎是有意义的。

现在,由于控制器类很大,所以这个给定的存储库不会被使用的可能性更大。正如我假设(可能是错误的)这种实例化 DC 是一项昂贵的操作,我宁愿避免这样做。使用服务定位器模式允许我将实例化推迟到实际需要上下文时,但鉴于上述链接中反对它的有效参数,我宁愿避免它。

所以我想知道的是,在上述情况下是否有一种更有效的方式来使用依赖注入,这会阻止我不必要地实例化我的存储库和底层数据上下文。

4

3 回答 3

2

我认为答案取决于您的存储库如何管理连接。如果它在构建时打开了与数据库的连接,那么我认为问题出在您的存储库上,而不是依赖注入。您的存储库应仅在发出请求时打开连接,并在收到响应后立即关闭它。遵循这种模式,依赖注入仍然有意义。


根据您的更新,您最好还是使用 DI,因为 EF 在构造时不会打开与数据库的连接,只有在发出请求时才会打开。您的数据上下文足够小,值得为每个请求创建上下文所需的少量开销。


还有一条评论:您还应该考虑将您的数据上下文注入到您的存储库中,并让您的 DI 容器控制上下文的生命周期。这允许您在单个请求期间在一个或多个存储库中使用相同的上下文。这是一个很好的资源,解释了如何在 ASP.NET MVC 中使用实体框架实现存储库和工作单元模式

于 2013-01-03T20:31:21.997 回答
2

由于控制器类很大,连接不会用于任何给定构造的可能性更大,因此实例化存储库并使用标准的基于构造函数的 DI 打开连接是没有意义的。

而是注入 a Lazy、 aFunc或工厂:

public class MyController
{
    // Use constructor injection to populate this.
    private Func<MyRepository> _repository;

    public void GetData()
    {
        using (var repository = _repository())
        {
            // ...
        }
    }
}

这样,您可以避免创建实际实例,直到您需要它们。

@sellmeadog 的回答也很好。

于 2013-01-03T20:35:10.300 回答
2

您在问是否应该将数据库连接注入 Repository 构造函数?您可以尝试使用抽象工厂设计模式注入数据库连接工厂而不是实际的数据库连接。

public class MyController
{
    public void GetData()
    {
        using (var repository = new Repository(IDatabaseConnectionFactory dbConnFac))
        {
            // Use the repository which disposes of a database connection
            // at the end of its life.
        }
    }

    // Lots of other methods.
}

通过这种方式,您可以获得依赖注入的好处,同时仍然允许存储库管理其数据库连接的生命周期。

于 2013-01-03T20:37:56.380 回答