开发者

Entity Framework "An object with the same key already exists in the ObjectStateManager." - I can't understand how, or what to do from here

开发者 https://www.devze.com 2023-03-11 02:08 出处:网络
I\'m building a MVC3 project, using Razor and Entity Framework code first. I have two models: public class Translation

I'm building a MVC3 project, using Razor and Entity Framework code first. I have two models:

public class Translation
{
    public int TranslationId { get; set; }
    public string Pt { get; set; }
    public string Es { get; set; }
    public string E开发者_运维问答n { 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; }   
}

I created the PagesController for CRUD for the Page model. Then I edited the Create and Edit views adding inputs for the Translation properties:

<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>

It works well on Create, adding two new lines to the Translations table (one refered by Title_TranslationId and the other Description_TranslationId) with the input contents. But when Updating, I get the mentioned error at line:

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

The PagesController is as it was created, so no extra attaches are being made. If I delete one of the Translations inputs at the Edit view, it doesn't throw the error, but doesn't update the translations anyway.

The PagesController code:

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);
    }
}

Note that ViewBag.ParentPageId feeds a Pages list that i didn't include in the view code, because it works if I remove the Translation stuff.

Any ideas?

EDIT: Maybe it is too complicated for EF to handle? Maybe I should change my aproach.


SOLVED

I was making two beginners' mistakes.

Mistake #1: Forgot to add the Translation properties Id in the view, so they can be bind in the POST method:

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

Mistake #2: Translation properties, as they are instances of the Translation class, must be set as modified before updating:

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

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

It works now. I lost a few hours but at least I think I've learned some stuff :)


Try using db.Pages.Attach(page);
db.ObjectStateManager.ChangeObjectState(page, EntityState.Modified);
instead of db.Entry(page).State = EntityState.Modified; it will attach the entity as modified


i'm using this because I have already created a new instance, and populated the properties I need to update.

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);
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号