首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IEntityChangeTracker的多个实例不能引用实体对象

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

Stack Overflow用户
提问于 2015-06-24 13:19:07
回答 3查看 630关注 0票数 1

我开始在我的MVC5代码-第一应用程序中使用尼尼姆。这是我的NinjectWebCommon.cs:

代码语言:javascript
复制
private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        try
        {
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            kernel.Bind<CMSContext>()
                .ToSelf()
                //.InSingletonScope();
                .InRequestScope();

            kernel.Bind<IExecutiveRepository>()
                .To<ExecutiveRepository>();

            kernel.Bind<IExecutiveSectionRepository>()
                .To<ExecutiveSectionRepository>();

            kernel.Bind<IExecutiveSectionMappingRepository>()
                .To<ExecutiveSectionMappingRepository>();

            kernel.Bind<IUserRepository>()
                .To<UserRepository>();

            kernel.Bind<IContentRepository>()
                .To<ContentRepository>();

            RegisterServices(kernel);
            return kernel;
        }
        catch
        {
            kernel.Dispose();
            throw;
        }
    }

我尝试了.InSingletonScope()和.InRequestScope(),但是仍然得到了‘实体对象不能被多个IEntityChangeTracker实例引用’错误。这是我的界面:

代码语言:javascript
复制
    public interface IExecutiveRepository : IDisposable
{
    IEnumerable<Executive> GetExecutives();
    Executive GetExecutiveById(int executiveId);
    void InsertExecutive(Executive executive);
    void UpdateExecutive(Executive executive);
    void DeleteExecutive(int executiveId);
    void Save();
}

这是我的混凝土:

代码语言:javascript
复制
 public class ExecutiveRepository : IExecutiveRepository, IDisposable
{
    private CMSContext context;

    public ExecutiveRepository(CMSContext context)
    {
        this.context = context;
    }

    public IEnumerable<Executive> 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);
    }
}

这里是控制器(最相关的部分):

代码语言:javascript
复制
 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<ExecutiveRepository>();
        userRepository = _kernel.Get<UserRepository>();
        executiveSectionRepository = _kernel.Get<ExecutiveSectionRepository>();
        executiveSectionMappingRepository = _kernel.Get<ExecutiveSectionMappingRepository>();
        contentRepository = _kernel.Get<ContentRepository>();
    }
 ...

不知道我做错了什么,但在增加一个新的‘执行’it炸弹.我确实理解它试图使用不同的上下文,这就是问题所在,但我只是不知道如何修复它。显然,NinjectWebCommon.cs类中的一行:

代码语言:javascript
复制
 kernel.Bind<CMSContext>()
                .ToSelf()
                //.InSingletonScope();
                .InRequestScope();

应该是解决办法,但不是.有什么想法/建议吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-06-24 14:50:56

如果您还没有使用NUGET Ninject.Web.Mvc,那么您应该使用它。这将配置您的应用程序,使其可以使用Ninject,而不是绑定。从我在CreateKernel()方法中可以看到的情况来看,您似乎已经相当熟悉绑定方面的内容了。

一旦您的绑定到位,您就不应该在控制器中创建内核,这是因为Ninject.Web.Mvc库将Ninject配置为在幕后为您创建控制器。因此,添加到它们中的任何依赖项都应该自动解决。

因此,可以使用构造函数注入来解决依赖关系:

代码语言:javascript
复制
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]属性:

代码语言:javascript
复制
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);
    }
}
票数 3
EN

Stack Overflow用户

发布于 2015-06-24 13:34:32

您正在为每个控制器创建一个内核。

InRequestScope只确保每个内核每个请求有一个实例。

因此,您需要调整内核的设置,以便每个web应用程序只有一个内核。请参见:

票数 2
EN

Stack Overflow用户

发布于 2015-06-24 13:34:21

这可能回答不了问题。但我倾向于使用EF为您提供的IDbContextFactory,并这样做:

代码语言:javascript
复制
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;
    }
}

然后绑定它,当您需要上下文时,您可以这样做:

代码语言:javascript
复制
public class ExecutiveRepository : IExecutiveRepository, IDisposable
{
    private readonly CMSContext context;

    public ExecutiveRepository(IDefaultContextFactory contextFactory)
    {
        this.context = contextFactory.Create();
    }
}

我相信@BatteryBackupUnit是正确的,我也会考虑在上下文中使用上面的模式。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31027733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档