【问题标题】:An entity object cannot be referenced by multiple instances of IEntityChangeTracker errorIEntityChangeTracker错误的多个实例不能引用实体对象
【发布时间】:2014-08-13 14:22:56
【问题描述】:

我知道这个问题有很多重复,但我找不到适合我的情况的问题。

所以我正在使用 ASP.NET MVC 4 + Entity Framework + Ninject 使用存储库模式(我看到很多提到存储库 + 工作单元模式?这可能是我的问题的潜在解决方案,但我不知道如何来实现它)。

当我尝试添加新帖子时,在以下代码行中出现“一个实体对象无法被多个 IEntityChangeTracker 实例引用”错误

context.Posts.Add(post);

这是我的完整实现:​​

具体仓库

public class EFBlogRepository : IBlogRepository
{
    private readonly EFDbContext context;

    public EFBlogRepository(EFDbContext dbcontext)
    {
        context = dbcontext;
    }

    //add post
    public int AddPost(Post post)
    {
        context.Posts.Add(post);
        context.SaveChanges();
        return post.PostID;
    }

    public Category Category(int id)
    {
        return context.Categories.FirstOrDefault(c => c.CategoryID == id);
    }

    public Tag Tag(int id)
    {
        return context.Tags.FirstOrDefault(t => t.TagID == id);
    }
}

界面

public interface IBlogRepository
{
    int AddPost(Post post);
    Category Category(int id);
    Tag Tag(int id);
}

我的控制器

public class AdminController : Controller
{
    private IBlogRepository repository;

    public AdminController(IBlogRepository repo)
    {
        repository = repo;
    }

    [HttpPost]
    public ContentResult AddPost(Post post)
    {
        string json;

        ModelState.Clear();

        if (TryValidateModel(post))
        {
            var id = repository.AddPost(post);

            json = JsonConvert.SerializeObject(new
            {
                id = id,
                success = true,
                message = "Post added successfully."
            });
        }
        else
        {
            json = JsonConvert.SerializeObject(new
            {
                id = 0,
                success = false,
                message = "Failed to add the post."
            });
        }
        return Content(json, "application/json");
    }
}

我认为以上任何一个都不是问题的根源,我认为问题出在我的自定义模型绑定器中

public class PostModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var post = (Post)base.BindModel(controllerContext, bindingContext);

        var repository = DependencyResolver.Current.GetService<IBlogRepository>();

        if (post.Category != null)
            post.Category = repository.Category(post.Category.CategoryID);

        var tags = bindingContext.ValueProvider.GetValue("Tags").AttemptedValue.Split(',');

        if (tags.Length > 0)
        {
            post.Tags = new List<Tag>();

            foreach (var tag in tags)
            {
                post.Tags.Add(repository.Tag(int.Parse(tag.Trim())));
            }
        }

        return post;
    }
}

还有我的 global.asax.cs

ModelBinders.Binders.Add(typeof(Post), new PostModelBinder());

这是我的 Ninject 依赖解析器

public class NinjectDependencyResolver: IDependencyResolver
{
    private IKernel kernel;

    public NinjectDependencyResolver()
    {
        kernel = new StandardKernel();
        AddBindings();
    }

    public object GetService(Type serviceType)
    {
        return kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return kernel.GetAll(serviceType);
    }

    private void AddBindings()
    {
        kernel.Bind<IBlogRepository>().To<EFBlogRepository>();
        kernel.Bind<IAuthProvider>().To<FormsAuthProvider>();
    }
}

【问题讨论】:

    标签: c# asp.net-mvc entity-framework ninject custom-model-binder


    【解决方案1】:

    您应该将您的上下文在 ninject 绑定中绑定为 InRequestScope

    kernel.Bind<EFDbContext >().To<EFDbContext >().InRequestScope();
    

    正如错误所说,一个实体不能绑定到多个 EF 上下文。似乎您正在从一个上下文中检索实体,然后将其添加到另一个上下文中。使用上面的行,您告诉 Ninject 使用相同的上下文实例来服务于同一 HTTP 请求中的所有依赖项。

    正在创建两个存储库。一个在控制器IBlogRepository repository 中,另一个在模型绑定器var repository = DependencyResolver.Current.GetService&lt;IBlogRepository&gt;() 中。在修复之前,每个存储库都有一个新的上下文实例,从而导致错误。修复后,两个存储库将共享同一个上下文实例。

    【讨论】:

    • 谢谢,我试过了,还是报错
    • 再次感谢,记住您的回答后,我继续下载 ninject mvc 扩展并删除了我自己的依赖解析器,然后我在绑定中添加了 InRequestScope,现在一切正常。跨度>
    • @EricWang 也许应该使用_kernel.Bind&lt;IBlogRepository&gt;().To&lt;BlogRepository&gt;().InSingletonScope();
    • @baozi 这真的没有必要,因为存储库将共享相同的 EFDbContext 依赖项并且它们没有状态。它不会造成任何伤害。
    • @EricWang 这很有趣,因为我昨天遇到了同样的问题,但在我做出改变后它就消失了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    • 2011-10-12
    • 1970-01-01
    相关资源
    最近更新 更多