C# entity对象不能被多个IEntityChangeTracker错误实例引用
我知道这个问题有很多重复的地方,但我找不到一个适合我的情况 因此,我使用ASP.NET MVC 4+实体框架+Ninject使用存储库模式(我看到很多人提到存储库+工作单元模式?这可能是解决我问题的一个潜在方法,但我不知道如何实现它) 当我尝试添加一篇新文章时,在下面的代码行中出现了“entity对象不能被IEntityChangeTracker的多个实例引用”错误C# entity对象不能被多个IEntityChangeTracker错误实例引用,c#,asp.net-mvc,entity-framework,ninject,custom-model-binder,C#,Asp.net Mvc,Entity Framework,Ninject,Custom Model Binder,我知道这个问题有很多重复的地方,但我找不到一个适合我的情况 因此,我使用ASP.NET MVC 4+实体框架+Ninject使用存储库模式(我看到很多人提到存储库+工作单元模式?这可能是解决我问题的一个潜在方法,但我不知道如何实现它) 当我尝试添加一篇新文章时,在下面的代码行中出现了“entity对象不能被IEntityChangeTracker的多个实例引用”错误 context.Posts.Add(post); 以下是我的全部实施: 混凝土仓库 public class EFBlogRep
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;
}
}
这是我的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>();
}
}
公共类NinjectDependencyResolver:IDependencyResolver
{
私有IKernel内核;
公共NinjectDependencyResolver()
{
内核=新的标准内核();
AddBindings();
}
公共对象GetService(类型serviceType)
{
返回kernel.TryGet(serviceType);
}
公共IEnumerable GetServices(类型serviceType)
{
返回kernel.GetAll(serviceType);
}
私有void AddBindings()
{
kernel.Bind().To();
kernel.Bind().To();
}
}
您应该将ninject绑定中的上下文绑定为RequestScope中的
kernel.Bind<EFDbContext >().To<EFDbContext >().InRequestScope();
kernel.Bind().To().InRequestScope();
正如错误所说,一个实体不能绑定到多个EF上下文。看起来您正在从一个上下文中检索实体,然后将其添加到另一个上下文中。使用上面这行代码,您告诉Ninject使用相同的上下文实例来服务同一HTTP请求中的所有依赖项
正在创建两个存储库。一个在控制器
IBlogRepository repository
中,另一个在模型绑定器var repository=dependencysolver.Current.GetService()
中。在修复之前,每个存储库都有一个新的上下文实例,从而导致错误。修复后,两个存储库将共享同一个上下文实例。谢谢,我试过了,错误仍然存在。再次感谢,记住您的答案后,我继续下载ninject mvc扩展并删除了我自己的依赖项解析程序,然后在绑定中添加了InRequestScope,现在一切正常了。@EricWang可能应该使用\u kernel.Bind().To().InSingletonScope()
@baozi这真的没有必要,因为存储库将共享相同的EFDbContext
依赖项,并且它们没有状态。“这不会有什么害处的。”EricWang说,这很有趣,因为我昨天也遇到了同样的问题,在我做出改变后,问题就消失了。
kernel.Bind<EFDbContext >().To<EFDbContext >().InRequestScope();