【问题标题】:Ninject caching an injected DataContext? Lifecycle Management?Ninject 缓存注入的 DataContext?生命周期管理?
【发布时间】:2011-05-29 20:32:18
【问题描述】:

我的存储库中出现了一系列非常奇怪的错误。未找到或更改行,2 次更新中有 1 次失败......没有任何意义。

就好像我的 DataContext 实例被缓存了......没有任何意义,我正在考虑转行。

然后我注意到 DataContext 实例是使用依赖注入和 Ninject 传入的(这是我第一次使用 DI...)。我撕掉了依赖注入,一切都恢复了正常。即刻。

所以依赖注入是问题所在,但我仍然不知道为什么。我推测 Ninject 正在缓存注入的 DataContext。

这是正确的吗?

编辑:

Ninject绑定如下:

Bind<IPupilBlockService>().To<SqlPupilBlockService>()
   .WithConstructorArgument("db", new dbDataContext());

【问题讨论】:

  • 在这种情况下,作为一种猜测,我只能认为这实际上取决于 IPupilBlockService 实现和使用它的客户端的生命周期。 HTH

标签: dependency-injection datacontext ninject lifecycle


【解决方案1】:

对于生命周期必须显式管理的任何对象(例如实现IDisposable 的对象)或对用户很重要的对象,尽量不要注入它们,而是注入允许创建此类对象的工厂。例如定义这个接口:

public interface IDbDataContextFactory
{
    dbDataContext CreateNew();
}

并按如下方式使用:

public class SqlPupilBlockService
{
    private IDbDataContextFactory contextFactory;

    public SqlPupilBlockService(
        IDbDataContextFactory contextFactory)
    {
        this.contextFactory = contextFactory;
    }

    public void DoSomeOperation()
    {
        using (var db = this.contextFactory.CreateNew())
        {
           // use the dbDataContext here.
        }
    }
}

的实现会非常简单,如下所示:

public class DbDataContextFactory : IDbDataContextFactory
{
    public dbDataContext CreateNew()
    {
        return new dbDataContext();
    }
}

注册过程如下:

Bind<IDbDataContextFactory>().To<DbDataContextFactory>();

使用工厂非常明确谁是创建对象的所有者以及谁应该控制其生命周期。这使您的代码更具可读性并遵循principle of least surprise。

更新

自我提交此答案以来已过去一年多。我现在不使用工厂,而是经常注入数据上下文本身,并在每个(Web)请求的基础上注册它。然而;可能需要改变您设计应用程序的方式,因此一如既往:这取决于。请看this answer。

【讨论】:

  • 我喜欢最小惊喜的原则!很好的答案,我喜欢这种想法和模式。我会测试看看它是否解决了我的问题,如果解决了,你会得到饼干。现在,+1。
  • 顺便说一句。非科学研究证明,有关 IoC 容器的所有问题中有 86.3% 可以通过使用工厂来解决 :-)
  • 实现了梦想。整齐地分开关注点。我控制的参数。需要最少的依赖注入。我的知识是逐渐增加的,而不是急剧增加的。惊喜被最小化。我继续前进。圣诞快乐。
【解决方案2】:

@Steven 给出了很好的解释,但实际上,Ninject 已经为您提供了一种方法来指定为每个请求生成一个实例:InRequestScope。

Bind<IPupilBlockService>()
   .To<SqlPupilBlockService>()
   .InRequestScope()
   .WithConstructorArgument("db", new dbDataContext());

【讨论】:

    【解决方案3】:

    看看Activation Behaviours。您的 DataContext 可能被绑定在 Singleton 范围内,或者其他范围之一,这将导致从内核返回相同的实例,具体取决于您的调用上下文。

    (我对 ninject 不太熟悉,但考虑到瞬态范围是默认值,我希望在您的应用程序代码中的某个地方,DataContext 被明确定义为具有非瞬态范围)

    【讨论】:

    • 不,我刚刚使用了 Ninject 默认设置。请参阅编辑。
    猜你喜欢
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2020-04-27
    • 2012-11-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多