【发布时间】:2011-12-05 03:06:28
【问题描述】:
我有一个数据库模型,我想用多个视图对其进行编辑。我的实际数据库模型比我在这里展示的要大得多。
数据库模型: PersonModel
public class PersonModel {
public Int32 Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Description { get; set; }
}
然后我有两个视图,EditPersonName.cshtml 和 EditPersonDescription.cshtml,使用户能够修改 PersonModel 的不同部分。
视图 1: EditPersonName.cshtml
@model EditPersonNameModel
@using (Html.BeginForm()) {
<div class="editor-label">@Html.LabelFor(m => m.FirstName)</div>
<div class="editor-field">@Html.TextBoxFor(m => m.FirstName)</div>
<div class="editor-label">@Html.LabelFor(m => m.LastName)</div>
<div class="editor-field">@Html.TextBoxFor(m => m.LastName)</div>
<input type="submit" value="Save" />
}
视图 2: EditPersonDescription.cshtml
@model EditPersonDescriptionModel
@using (Html.BeginForm()) {
<div class="editor-label">@Html.LabelFor(m => m.Description)</div>
<div class="editor-field">@Html.TextBoxFor(m => m.Description)</div>
<input type="submit" value="Save" />
}
我希望将它们分别链接到 EditPersonNameModel 和 EditPersonDescriptionModel,而不是将每个视图直接绑定到 PersonModel。
查看模型 1: EditPersonNameModel
public class EditPersonNameModel {
public string FirstName { get; set; }
public string LastName { get; set; }
}
查看模型 2: EditPersonDescriptionModel
public class EditPersonDescriptionModel {
public string Description { get; set; }
}
我想值得一提的是,我正在使用 EF 的 DbContext 模式。
public class PersonDbContext : DbContext {
public DbSet<PersonModel> Persons { get; set; }
}
现在是我的控制器,事情开始崩溃了!
控制器: PersonController
public class PersonController {
private PersonDbContext = new PersonDbContext();
[HttpGet]
public ActionResult EditName(int id) {
// ??? ---- #1 -----
}
[HttpPost]
public ActionResult EditName(EditPersonNameModel model, int id) {
if (ModelState.IsValid) {
// ??? ---- #2 ----- ??? Update FirstName,LastName ONLY
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
[HttpGet]
public ActionResult EditDescription(int id) {
// ??? ---- #3 -----
}
[HttpPost]
public ActionResult EditDescription(EditPersonDescriptionModel model, int id) {
if (ModelState.IsValid) {
// ??? ---- #4 ----- ??? Update Description ONLY
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
}
我的问题是我不知道在上面的 ??? ---- #X ----- 块中放什么。显然#1 和#3 将非常相似,#2 和#4 也是如此。
有人建议我使用AutoMapper。这有助于从 Db 模型到视图模型,但反之则不行。
目前我的#1 代码块如下所示:
[HttpGet]
public ActionResult EditName(int id) {
PersonModel person = db.Persons.Find(id);
if (person == null) {
return HttpNotFound();
}
EditPersonNameModel viewModel;
AutoMapper.Mapper.CreateMap<PersonModel, EditPersonNameModel>();
viewModel = AutoMapper.Mapper.Map<PersonModel, EditPersonNameModel>(person);
return View(viewModel);
}
我的#2 代码块如下所示:
[HttpPost]
public ActionResult EditName(EditPersonNameModel viewModel, int id) {
if (ModelState.IsValid) {
PersonModel person = db.Persons.Find(id);
if (person == null) {
return HttpNotFound();
}
EditPersonNameModel viewModel;
AutoMapper.Mapper.CreateMap<EditPersonNameModel, PersonModel>();
person = AutoMapper.Mapper.Map<EditPersonNameModel, PersonModel>(viewModel);
db.Entry(person).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
#1 上面实际上工作正常。 AutoMapper 将从较大的 Person 对象映射到 EditPersonName 对象。
#2 已损坏。 AutoMapper 将从 EditPersonNameModel 对象映射到一个新的 Person 对象,因此db.Entry(person).State = EntityState.Modified 将抛出异常:
ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象。
我不需要 AutoMapper 来创建新对象,我需要映射到 现有 对象。要是有AutoMapper.Mapper.更新<EditPersonNameModel, PersonModel>(viewModel, person)就好了。
好的,现在这是一个很长的问题!感谢您的阅读,我非常感谢您的帮助!如果您熟悉 AutoMapper 并且知道我做错了什么,请告诉我。如果您阅读了此代码并知道完全不同的方法,请也告诉我!
谢谢!!!
更新 1
我有一个 #2 工作,但我不确定它有多好。
新#2
[HttpPost]
public ActionResult EditName(EditPersonNameModel viewModel, int id) {
if (ModelState.IsValid) {
PersonModel person = db.Persons.Find(id);
if (person == null) {
return HttpNotFound();
}
TryUpdateModel(person);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
请注意,TryUpdateModel 是在 person 而不是 viewModel 上调用的。我已经从数据库中获取了person,所以它已经完全填满了,带有一个 ID。 TryModelUpdate 方法使用IModelBinder 将属性从当前“mvc 请求上下文”映射到指定对象。因为我的PersonModel 和EditPersonNameModel 使用相同的命名属性,所以它可以工作。这确实是一个非常糟糕的解决方案,所以如果您知道更好的解决方案,请告诉我!
【问题讨论】: