На объектный объект нельзя ссылаться несколькими экземплярами ошибки IEntityChangeTracker
Я понимаю, что в этом вопросе много дубликатов, но я не смог найти тот, который соответствует моему сценарию.
Поэтому я использую 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>();
}
}
1 ответ
Вы должны связать свой контекст в непрямых привязках как InRequestScope
kernel.Bind<EFDbContext >().To<EFDbContext >().InRequestScope();
Как говорится в ошибке, один объект не может быть связан с более чем одним контекстом EF. Кажется, что вы извлекаете объект из одного контекста, а затем добавляете его в другой. Используя строку выше, вы говорите Ninject использовать один и тот же экземпляр контекста для обслуживания всех зависимостей в одном и том же HTTP-запросе.
Два хранилища создаются. Один в контроллере IBlogRepository repository
а другой в модели переплет var repository = DependencyResolver.Current.GetService<IBlogRepository>()
, Перед исправлением у каждого хранилища есть новый экземпляр контекста, вызывающий ошибку. После исправления оба хранилища будут использовать один и тот же экземпляр контекста.