编辑实体时的EF 4.1 Code-First和ASP MVC 3问题

时间:2011-04-12 15:41:03

标签: entity-framework asp.net-mvc-3 poco ef-code-first scaffolding

我用我的实体编码并创建了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 个答案:

答案 0 :(得分:1)

实际上你不需要查询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

答案 1 :(得分:0)

您无法附加图书,因为您已将图书加载到同一上下文中。一般方法是:

[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);
}
相关问题