C# 实体框架“;ObjectStateManager中已存在具有相同密钥的对象我能';我不知道该怎么做,或者该怎么做
我正在构建一个MVC3项目,首先使用Razor和实体框架代码。我有两种型号:C# 实体框架“;ObjectStateManager中已存在具有相同密钥的对象我能';我不知道该怎么做,或者该怎么做,c#,asp.net,asp.net-mvc,entity-framework,C#,Asp.net,Asp.net Mvc,Entity Framework,我正在构建一个MVC3项目,首先使用Razor和实体框架代码。我有两种型号: 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 in
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; }
}
我为页面模型的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>
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处理起来太复杂了?也许我应该换一个套路。试试使用
db.Pages.Attach(第页)
db.ObjectStateManager.ChangeObjectState(第页,EntityState.Modified);
而不是db.Entry(page).State=EntityState.Modified代码>
它将附加修改后的实体
我犯了两个初学者的错误
错误#1:忘记在视图中添加翻译属性Id,因此可以在POST方法中绑定它们:
@Html.HiddenFor(model => model.Title.TranslationId)
@Html.HiddenFor(model => model.Description.TranslationId)
错误#2:翻译属性是Translation类的实例,必须在更新之前设置为modified:
db.Entry(page.Title).State = EntityState.Modified;
db.Entry(page.Description).State = EntityState.Modified;
db.Entry(page).State = EntityState.Modified;
db.SaveChanges();
现在可以了。我损失了几个小时,但至少我认为我学到了一些东西:)我使用它是因为我已经创建了一个新实例,并填充了需要更新的属性
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);
您可以发布编辑控制器代码吗?您需要将模型类中的属性声明为virtual@jayantha,我现在就这么做了,并在Entities.cs中添加了外键,但现在它避免了错误“发生引用完整性约束冲突:定义引用约束的属性值在关系中的主体对象和从属对象之间不一致。“为什么不使用POCO实体生成器之类的工具生成模型类呢。您需要有几种方法来修复实体框架中的导航属性。我直到现在才知道。我在试一下……啊。由于某些原因,db(Models.AdminEntities的实例)不包含ObjectStateManager的定义:|
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);