Ninject: entity object cannot be referenced by multiple instances of IEntityChangeTracker

前端 未结 3 1141
攒了一身酷
攒了一身酷 2021-01-23 07:15

I am starting to use Ninject in my MVC5 code-first app. Here\'s my NinjectWebCommon.cs:

private static IKernel CreateKernel()
    {
        var kernel = new Stan         


        
相关标签:
3条回答
  • 2021-01-23 07:28

    You're creating a kernel per controller.

    InRequestScope only ensures one instance per request per kernel.

    So you need to adapt your setup of the kernel so there's only one kernel per web application. See:

    • Ninject.Web.Mvc
    • Tutorial
    • Youtube
    0 讨论(0)
  • 2021-01-23 07:30

    You should be using NUGET package Ninject.Web.Mvc if you aren't already. This configures your application ready to use Ninject, other than your bindings. It looks like you are reasonably familiar with the bindings side of things already from what I can see in your CreateKernel() method.

    Once your bindings are in place, you should not be creating Kernels in your controllers, this is because the Ninject.Web.Mvc library configures Ninject to create your controllers for you under the hood. Therefore any dependencies that you add to them should be automatically resolved.

    So, you can use constructor injection to resolve your dependencies:

    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);
        }
    }
    

    Or you can use the [Inject] attribute which has the same effect:

    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);
        }
    }
    
    0 讨论(0)
  • 2021-01-23 07:44

    This may not answer the question. But I tend to use the IDbContextFactory that EF provides you with and do something like this:

    public interface IDefaultContextFactory : IDbContextFactory<CMSContext> {}
    
    public class DefaultContextFactory : IDefaultContextFactory 
    {
        private readonly Lazy<CMSContext> lazyContext = new Lazy<CMSContext>(() => new CMSContext());
    
        public CMSContext Create() 
        {
            return lazyContext.Value;
        }
    }
    

    Then you just bind that, and when you need the context you can do something like this:

    public class ExecutiveRepository : IExecutiveRepository, IDisposable
    {
        private readonly CMSContext context;
    
        public ExecutiveRepository(IDefaultContextFactory contextFactory)
        {
            this.context = contextFactory.Create();
        }
    }
    

    I believe @BatteryBackupUnit is correct, I would also consider using the above pattern for contexts.

    0 讨论(0)
提交回复
热议问题