我正在构建一个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太复杂了?也许我应该改变我的方法。答案 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);