实体框架“ObjectStateManager中已存在具有相同密钥的对象。” - 我无法理解这里的方式或做法

时间:2011-06-07 01:27:31

标签: c# asp.net asp.net-mvc entity-framework

我正在构建一个MVC3项目,首先使用Razor和Entity Framework代码。我有两个模型:

public class Translation
{
    public int TranslationId { get; set; }
    public string Pt { get; set; }
    public string Es { get; set; }
    public string En { get; set; }
}

public class Page
{
    public int PageId { get; set; }
    public Translation Title { get; set; }
    public Translation Description { get; set; }

    public int? ParentPageId { get; set; } // page can have a parent page
    public Page ParentPage { get; set; }   
}

我为Page模型创建了用于CRUD的PagesController。然后我编辑了创建和编辑视图,为翻译属性添加输入:

<div class="editor-field">
   @Html.EditorFor(model => model.Title.Pt)
   @Html.ValidationMessageFor(model => model.Title.Pt)
</div>
<div class="editor-field">
   @Html.EditorFor(model => model.Title.Es)
   @Html.ValidationMessageFor(model => model.Title.Es)
</div>
<div class="editor-field">
   @Html.EditorFor(model => model.Title.En)
   @Html.ValidationMessageFor(model => model.Title.En)
</div>

<div class="editor-field">
   @Html.EditorFor(model => model.Description.Pt)
   @Html.ValidationMessageFor(model => model.Description.Pt)
</div>
<div class="editor-field">
   @Html.EditorFor(model => model.Description.Es)
   @Html.ValidationMessageFor(model => model.Description.Es)
</div>
<div class="editor-field">
   @Html.EditorFor(model => model.Description.En)
   @Html.ValidationMessageFor(model => model.Description.En)
</div>

在Create上运行良好,在Translations表中添加了两行(一个是Title_TranslationId引用的,另一个是Description_TranslationId)和输入内容。但是在更新时,我在行上得到了提到的错误:

db.Entry(page).State = EntityState.Modified;

PagesController就像它创建的那样,因此没有额外的附件。如果我在“编辑”视图中删除其中一个“翻译”输入,则不会抛出错误,但无论如何都不会更新翻译。

PagesController代码:

private AdminEntities db = new AdminEntities();
    public ViewResult Index()
    {
        return View(db.Pages.ToList());
    }
    public ViewResult Details(int id)
    {
        Page page = db.Pages.Find(id);
        return View(page);
    }
    public ActionResult Create()
    {
        ViewBag.ParentPageId = new SelectList(db.Pages, "ParentPageId", "Description");
        return View();
    } 
    [HttpPost]
    public ActionResult Create(Page page)
    {
        if (ModelState.IsValid)
        {
            db.Pages.Add(page);
            db.SaveChanges();
            return RedirectToAction("Index");  
        }
        ViewBag.ParentPageId = new SelectList(db.Pages, "ParentPageId", "Description", page.ParentPageId);
        return View(page);
    }
    public ActionResult Edit(int id)
    {
        Page page = db.Pages.Find(id);
        ViewBag.ParentPageId = new SelectList(db.Pages, "ParentPageId", "Description", page.ParentPageId);            
        return View(page);
    }
    [HttpPost]
    public ActionResult Edit(Page page)
    {
        if (ModelState.IsValid)
        {
            db.Entry(page).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.ParentPageId = new SelectList(db.Pages, "ParentPageId", "Description", page.ParentPageId);
        return View(page);
    }
}

请注意,ViewBag.ParentPageId会提供一个我未包含在视图代码中的页面列表,因为如果我删除了翻译内容,它就会有效。

有什么想法吗?

编辑:也许EF太复杂了?也许我应该改变我的方法。

3 个答案:

答案 0 :(得分:4)

解决

我犯了两个初学者的错误。

错误#1:忘记在视图中添加翻译属性ID,因此可以在POST方法中绑定它们:

@Html.HiddenFor(model => model.Title.TranslationId)
@Html.HiddenFor(model => model.Description.TranslationId)

错误#2:翻译属性,因为它们是翻译类的实例,必须在更新前设置为已修改:

db.Entry(page.Title).State = EntityState.Modified;
db.Entry(page.Description).State = EntityState.Modified;

db.Entry(page).State = EntityState.Modified;
db.SaveChanges();

现在有效。我失去了几个小时,但至少我认为我已经学到了一些东西:)

答案 1 :(得分:1)

尝试使用  db.Pages.Attach(page);
db.ObjectStateManager.ChangeObjectState(page, EntityState.Modified);
 而不是db.Entry(page).State = EntityState.Modified;  它会将实体附加为修改后的

答案 2 :(得分:0)

我正在使用它,因为我已经创建了一个新实例,并填充了我需要更新的属性。

var key=this.CreateEntityKey("Pages",page); 
        ObjectStateEntry ose;
        if(this.ObjectStateManager.TryGetObjectStateEntry(key, out ose)){
            var entity=(Page)ose.Entity;
            Pages.Detach(entity);
        }
            this.Pages.Attach(page);
相关问题