EF 4.1 Code-First и ASP MVC 3 проблема при редактировании сущностей
Я закодировал свои сущности и создал DbContext. Затем я использовал MVC Scaffolding для создания простой формы CRUD для одного объекта. Пока все хорошо, все работает как рекламируется. Теперь я решил заменить сгенерированный скаффолдингом DbContext на простую обертку Service поверх DbContext. Все, что он делает, это делегирует DbContext.
Тем не менее, теперь у меня есть проблема в следующей строке при попытке изменить сущность:
service.Entry(Book).State = EntityState.Modified;
"Объект с таким же ключом уже существует в ObjectStateManager. ObjectStateManager не может отслеживать несколько объектов с одним и тем же ключом "
Мне удалось решить это так:
PropertyInfo[] infos = typeof(Book).GetProperties();
foreach (PropertyInfo info in infos)
{
info.SetValue(internalBook, info.GetValue(book, null), null);
}
По сути, я снова получаю объект и копирую свойства объекта, который был передан мне View. Я также отметил, что когда я получаю юридическое лицо, оно является доверенным лицом, а врученное мне - нет.
В чем может быть проблема?
Вот мой класс обслуживания:
public class BookService
{
private DbContext context;
private DbSet<Book> set;
public BookService(DbContext context, DbSet<Book> set) {
this.context = context;
this.set = set;
}
public IQueryable<Book> Query
{
get { return set; }
}
public virtual void Add(Book entity)
{
set.Add(entity);
}
public virtual void Remove(Book entity)
{
set.Remove(entity);
}
public virtual void SaveChanges() {
context.SaveChanges();
}
public List<Book> All() {
List<Book> books = set.ToList();
return books;
}
public DbEntityEntry<Book> Entry(Book book) {
return context.Entry(book);
}
}
Вот код действия редактора действия. Я прокомментировал оригинальный, сгенерированный скаффолдингом код:
[HttpPost]
public ActionResult Edit(Book book)
{
Book internalBook = service.Query.Single(b => b.Id == book.Id);
if (ModelState.IsValid)
{
PropertyInfo[] infos = typeof(Book).GetProperties();
foreach (PropertyInfo info in infos)
{
info.SetValue(internalBook, info.GetValue(book, null), null);
}
service.Entry(internalBook).State = EntityState.Modified;
service.SaveChanges();
//context.Entry(book).State = EntityState.Modified;
//context.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
2 ответа
Вы не можете прикрепить книгу, потому что вы загрузили ее в том же контексте. Общий подход таков:
[HttpPost]
public ActionResult Edit(Book book)
{
Book internalBook = service.Query.Single(b => b.Id == book.Id);
if (ModelState.IsValid)
{
service.Entry(internalBook).CurrentValues.SetValues(book);
service.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
На самом деле вам не нужно запрашивать книгу, вы можете просто использовать эти две строки:
service.Entry(book).State = EntityState.Modified;
service.SaveChanges();
Итак, это полный код:
[HttpPost]
public ActionResult Edit(Book book)
{
if (ModelState.IsValid)
{
service.Entry(book).State = EntityState.Modified;
service.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}
Вы можете скачать полное решение из этого поста: http://blog.jorgef.net/2011/04/ef-poco-proxies-in-mvc.html