EF的DbContext的单例范围

所以我目前正在使用一个使用Entity Framework的ASP.NET MVC Web应用程序,我也使用Ninject进行dependency injection。

所以基本上,目前,这是我用Ninject注册我的DbContext和服务的方式。

kernel.Bind().To().InSingletonScope(); kernel.Bind().To().InSingletonScope(); kernel.Bind().To().InSingletonScope(); kernel.Bind().To().InSingletonScope(); 

我用InSingletonScope注册它们,这意味着它们只会被创建一次并在应用程序的整个生命周期中使用(至少我是如何理解的)。

控制器:

 private IAccountService _accountService; public MemberController(IAccountService accountService) { _accountService = accountService; } 

但是,我深深感到这个单例范围会导致我的Web应用程序出现问题,特别是对于Entity Framework的上下文,因为它是单例。

我已经面临一个小问题,如果我使用SQL Management Studio手动更新数据库,我的Web应用程序的entity framework中的数据将不会更新,直到我重新启动应用程序(似乎是EF中的一些缓存机制)。

但是,如果我删除InSingletonScope ,我将从EF中随机获取错误,说:

IEntityChangeTracker的多个实例不能引用实体对象

我理解为什么会发生这种情况,因为AccountService初始化的DbContext可能与RegionService不同。 但我不知道如何解决这个问题。

我对dependency injection的理解仍然非常有限,所以有人可以建议吗?

编辑:我已经尝试过更换为InRequestScope以进行所有注射,但我仍然InRequestScope

IEntityChangeTracker的多个实例不能引用实体对象

尝试从我的应用程序中的另一个服务插入具有相关对象(外键)的新实体时。 这意味着他们仍在使用不同的DbContext,发生了什么?!

最后编辑:好的我发现了问题,这是我的缓存机制缓存了以前的请求,导致所有后续请求的关系问题。

单例范围对于您的上下文来说是一个非常糟糕的主意。 请求范围是您应该使用的,因为它实际上是请求生命周期中的单例。

至于为何在使用请求范围时遇到错误,我无法肯定地说。 假设您正在使用的实体都来自相同的上下文类型,并且您正确地在需要的任何地方正确地注入上下文,那么应该永远不会有多个上下文实例。

编辑

重新阅读您的问题之后,听起来好像您的服务实际上正在初始化其构造函数中的上下文。 如果是这样的话,那就是你的问题。 您的上下文应该注入您的服务,即:

 public class AccountService : IAccountService { protected readonly DbContext context; public AccountService(DbContext context) { this.context = context; } ... } 

然后,Ninject将在新建任何服务时正确地注入请求范围的MyApplicationContext实例。

我终于通过使用InRequestScope而不是InSingletonScope来解决这个问题。

最初,由于我在服务层上的现有缓存机制,在更改为InRequestScope后,我仍然面临同样的问题。

因此,所有后续请求都使用初始缓存的实体对象,这就是我从EF获取多个实例错误的原因。

如果你还在面对

IEntityChangeTracker的多个实例不能引用实体对象

更改为InRequestScope后出现错误,请确保您的实体不会以某种方式缓存或存储以供后续HTTP请求使用。

Dan,当您为整个应用程序设置单个DBContext时,您正在创建瓶颈。 在底层,Entity Framework将相当有效地处理您需要的对象数量。 如果你深入到内部,那么联系数据库的实际对象也会做同样的事情。 因此,通过制作单例进行优化的尝试实际上可能会产生一个非常大的问题。