Entity framework EF 4.1编辑实体时代码优先和ASP MVC 3问题
我用DbContext对实体进行编码并创建了DbContext。然后我使用MVC脚手架为一个实体创建简单的CRUD表单。到目前为止,一切都很好,正如广告所宣传的那样。 现在,我决定用DbContext上的简单服务包装器替换脚手架生成的DbContext。它所做的只是委托给DbContext 但是,现在我在尝试编辑实体时,在以下行出现了问题:Entity framework EF 4.1编辑实体时代码优先和ASP MVC 3问题,entity-framework,asp.net-mvc-3,poco,ef-code-first,scaffolding,Entity Framework,Asp.net Mvc 3,Poco,Ef Code First,Scaffolding,我用DbContext对实体进行编码并创建了DbContext。然后我使用MVC脚手架为一个实体创建简单的CRUD表单。到目前为止,一切都很好,正如广告所宣传的那样。 现在,我决定用DbContext上的简单服务包装器替换脚手架生成的DbContext。它所做的只是委托给DbContext 但是,现在我在尝试编辑实体时,在以下行出现了问题: service.Entry(Book).State = EntityState.Modified; “ObjectStateManager中已存在具有相同
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);
}
基本上,我再次获取实体,并从视图交给我的实体复制属性。我还注意到,当我获得实体时,它是代理,而交给我的那一只不是
有什么问题吗
这是我的服务课:
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)
{
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);
}
您可以从这篇文章下载完整的解决方案:行
service.Entry(Book.State=EntityState.Modified)前面的代码是什么代码>?我已将问题编辑为包含您要求的代码。当您删除该行时会发生什么?它不保存更改吗?我原以为上下文可以跟踪更改,而无需手动更改EntityState。@Carlino,确切地说,id不保存更改。正如我所提到的,代码是由Mvc Scaffolding,works生成的,我试图以尽可能少的方式修改它。我注意到的一件事是,在我的fix internalBook中,它实际上是一个代理,而我作为参数接收的book则不是。这与我所做的类似。。。但我猜,搭建好的代码会用每个请求初始化新的上下文吗?如下所示:private BooksAndAuthorsWebContext context=new BooksAndAuthorsWebContext();这意味着每个请求都会实例化新控制器。必须使用每个请求初始化上下文。如果您没有为每个请求创建新的上下文,您将遇到严重的问题:我正在使用Ninject。如果我理解正确,InRequestScope应该可以做到这一点
[HttpPost]
public ActionResult Edit(Book book)
{
if (ModelState.IsValid)
{
service.Entry(book).State = EntityState.Modified;
service.SaveChanges();
return RedirectToAction("Index");
}
return View(book);
}