关于依赖注入:Ninject缓存注入的DataContext?

Ninject caching an injected DataContext? Lifecycle Management?

我有一系列非常奇怪的错误被扔进了我的仓库。未找到或更改行,2个更新中的1个失败…没有任何意义。

就好像我的DataContext实例正在缓存中…没什么道理,我正在考虑换个职业。

然后我注意到DataContext实例是使用依赖项注入和Ninject传入的(这是我第一次使用DI…)。我抽出依赖注射,一切恢复正常。立刻。

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

这是正确的吗?

编辑:

ninject绑定如下:

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


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

1
2
3
4
public interface IDbDataContextFactory
{
    dbDataContext CreateNew();
}

使用方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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.
        }
    }
}

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

1
2
3
4
5
6
7
public class DbDataContextFactory : IDbDataContextFactory
{
    public dbDataContext CreateNew()
    {
        return new dbDataContext();
    }
}

注册过程如下:

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

工厂的使用使得它非常明确谁是被创建对象的所有者,谁应该控制它的生命周期。这使您的代码更易于阅读,并遵循最不令人惊讶的原则。

更新

我提交这个答案已经一年多了。现在,我不再使用工厂,而是经常注入数据上下文本身,并根据每个(Web)请求对其进行注册。但是,可能需要改变您设计应用程序的方式,就像往常一样:这取决于情况。请看一下这个答案。


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

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


看看激活行为。可能您的DataContext被绑定在单个作用域中,或者其他作用域中的某个作用域将导致从内核返回同一实例,具体取决于您的调用上下文。

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