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

我只是一个虾纸丫 提交于 2019-12-02 07:21:20

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

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:

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!