Ninject:实体对象不能被IEntityChangeTracker的多个实例引用
我开始在我的MVC5代码优先应用程序中使用Ninject。 这是我的NinjectWebCommon.cs:
private static IKernel CreateKernel() { var kernel = new StandardKernel(); try { kernel.Bind<Func>().ToMethod(ctx => () => new Bootstrapper().Kernel); kernel.Bind().To(); kernel.Bind() .ToSelf() //.InSingletonScope(); .InRequestScope(); kernel.Bind() .To(); kernel.Bind() .To(); kernel.Bind() .To(); kernel.Bind() .To(); kernel.Bind() .To(); RegisterServices(kernel); return kernel; } catch { kernel.Dispose(); throw; } }
我试过.InSingletonScope()以及.InRequestScope()但我仍然得到’ 实体对象不能被多个IEntityChangeTracker实例引用 ‘错误。 这是我的界面:
public interface IExecutiveRepository : IDisposable { IEnumerable GetExecutives(); Executive GetExecutiveById(int executiveId); void InsertExecutive(Executive executive); void UpdateExecutive(Executive executive); void DeleteExecutive(int executiveId); void Save(); }
这是我的具体内容:
public class ExecutiveRepository : IExecutiveRepository, IDisposable { private CMSContext context; public ExecutiveRepository(CMSContext context) { this.context = context; } public IEnumerable GetExecutives() { return context.Executives.ToList(); } public Executive GetExecutiveById(int id) { return context.Executives.Find(id); } public void InsertExecutive(Executive executive) { context.Executives.Add(executive); } public void DeleteExecutive(int executiveId) { Executive executive = context.Executives.Find(executiveId); context.Executives.Remove(executive); } public void UpdateExecutive(Executive executive) { context.Entry(executive).State = EntityState.Modified; } public void Save() { context.SaveChanges(); } private bool disposed = false; protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { context.Dispose(); } } this.disposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } }
这是控制器(顶部相关部分):
public class ExecutiveController : Controller { private IExecutiveRepository executiveRepository; private IUserRepository userRepository; private IExecutiveSectionRepository executiveSectionRepository; private IExecutiveSectionMappingRepository executiveSectionMappingRepository; private IContentRepository contentRepository; private Ninject.IKernel _kernel = new StandardKernel(); //[Inject] public ExecutiveController() { executiveRepository = _kernel.Get(); userRepository = _kernel.Get(); executiveSectionRepository = _kernel.Get(); executiveSectionMappingRepository = _kernel.Get(); contentRepository = _kernel.Get(); } ...
不知道我做错了什么,但在添加一个新的’执行’它炸弹…我明白它试图使用单独的上下文,这是问题,但我只是不知道如何解决它。 显然,NinjectWebCommon.cs类中的行:
kernel.Bind() .ToSelf() //.InSingletonScope(); .InRequestScope();
应该是修复,但它不是……任何想法/建议?
你应该使用NUGET包Ninject.Web.Mvc
如果你还没有。 这会将您的应用程序配置为使用Ninject,而不是绑定。 看起来你已经熟悉了我在CreateKernel()
方法中看到的东西的绑定方面。
绑定到位后,您不应该在控制器中创建内核,这是因为Ninject.Web.Mvc
库配置Ninject为您创建控制器。 因此,应自动解决您添加到它们的任何依赖项。
因此,您可以使用构造函数注入来解决依赖关系:
public class ExecutiveController : Controller { private IExecutiveRepository ExecutiveRepository; private IUserRepository UserRepository; private IExecutiveSectionRepository ExecutiveSectionRepository; private IExecutiveSectionMappingRepository ExecutiveSectionMappingRepository; private IContentRepository ContentRepository; public ExecutiveController( IExecutiveRepository executiveRepository, IUserRepository userRepository, IExecutiveSectionRepository executiveSectionRepository, IExecutiveSectionMappingRepository executiveSectionMappingRepository, IContentRepository contentRepository) { // Set the field values this.ExecutiveRepository = executiveRepository, this.UserRepository = userRepository, this.ExecutiveSectionRepository = executiveSectionRepository, this.ExecutiveSectionMappingRepository = executiveSectionMappingRepository, this.ContentRepository = contentRepository; } public ActionResult Index(int id) { // Use one of your dependencies... var executive = this.executiveRepository.GetExecutiveById(id); } }
或者您可以使用具有相同效果的[Inject]
属性:
public class ExecutiveController : Controller { [Inject] public IExecutiveRepository executiveRepository { get; set; } [Inject] public IUserRepository userRepository { get; set; } [Inject] public IExecutiveSectionRepository executiveSectionRepository { get; set; } [Inject] public IExecutiveSectionMappingRepository executiveSectionMappingRepository { get; set; } [Inject] public IContentRepository contentRepository { get; set; } public ExecutiveController() { } public ActionResult Index(int id) { // Use one of your dependencies... var executive = this.executiveRepository.GetExecutiveById(id); } }
您正在为每个控制器创建一个内核。
InRequestScope
仅确保每个内核的每个请求一个实例。
所以你需要调整你的内核设置,这样每个web应用程序只有一个内核。 看到:
- Ninject.Web.Mvc
- 教程
- 的Youtube
这可能无法回答这个问题。 但我倾向于使用EF为您提供的IDbContextFactory
并执行以下操作:
public interface IDefaultContextFactory : IDbContextFactory {} public class DefaultContextFactory : IDefaultContextFactory { private readonly Lazy lazyContext = new Lazy (() => new CMSContext()); public CMSContext Create() { return lazyContext.Value; } }
然后你只需绑定它,当你需要上下文时,你可以做这样的事情:
public class ExecutiveRepository : IExecutiveRepository, IDisposable { private readonly CMSContext context; public ExecutiveRepository(IDefaultContextFactory contextFactory) { this.context = contextFactory.Create(); } }
我相信@BatteryBackupUnit是正确的,我也会考虑将上述模式用于上下文。
- ASP.NET MVC(异步)CurrentCulture不在Controller和View之间共享
- 为什么我不能在两个使用StateServer的Web应用程序之间共享会话状态? 我错过了什么?
- 在c#mvc中对单选按钮进行分组
- ASP.NET WebApi不接收post数据
- 如何在MVC htmlAttribute中设置禁用
- Mvc RenderAction性能与RenderPartial相比
- ‘System.Data.Entity.Migrations.DbMigrationsConfiguration`1’的类型初始值设定项引发exception
- 电话号码validationMVC
- 在ASP.NET Core 2.0 Web Api中返回“raw”json