经过一整天的研究,我有一些目前正在发挥作用的东西。但是,我不确定我是否真的了解导航属性和实体关系会发生什么,所以我担心我的代码将来可能会出现问题。我不得不手动将导航属性设置为“EntityState.Modified”。我的模型最终可能有许多级别的导航对象和集合。有更简单的方法来更新相关实体吗?如果没有更简单的方法,这种方法可以吗?
这是视图模型
public class ViewModel {
public ViewModel() { }
public ViewModel(Context context) {
this.Options = new SelectList(context.Options, "Id", "Name");
}
public Parent Parent { get; set; }
public SelectList Options { get; set; }
}
实体类
public class Parent {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ChildOne ChildOne { get; set; }
public virtual ChildTwo ChildTwo { get; set; }
}
public class ChildOne {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Parent Parent { get; set; }
public virtual int OptionId { get; set; }
public virtual Option Option { get; set; }
}
public class ChildTwo {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Parent Parent { get; set; }
public virtual int OptionId { get; set; }
public virtual Option Option { get; set; }
}
public class Option {
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<ChildOne> ChildrenOnes { get; set; }
public virtual ICollection<ChildTwo> ChildrenTwos { get; set; }
}
上下文
public class Context : DbContext {
public DbSet<Parent> Parents { get; set; }
public DbSet<ChildOne> ChildrenOnes { get; set; }
public DbSet<ChildTwo> ChildrenTwos { get; set; }
public DbSet<Option> Options { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Parent>()
.HasOptional(x => x.ChildOne)
.WithOptionalPrincipal(x => x.Parent);
modelBuilder.Entity<Parent>()
.HasOptional(x => x.ChildTwo)
.WithOptionalPrincipal(x => x.Parent);
}
}
控制器
private Context db = new Context();
public ActionResult Edit() {
ViewModel viewmodel = new ViewModel(db);
viewmodel.Parent = db.Parents.Find(1);
return View(viewmodel);
}
public void Save(Parent parent) {
if (ModelState.IsValid) {
db.Entry(parent).State = EntityState.Modified;
db.Entry(parent.ChildOne).State = EntityState.Modified;
db.Entry(parent.ChildTwo).State = EntityState.Modified;
db.SaveChanges();
}
}
并查看
@model MvcApp7.Models.ViewModel
<div id="Parent">
@Html.HiddenFor(model => model.Parent.Id)
@Html.TextBoxFor(model => model.Parent.Name)
<div id="ChildOne">
@Html.HiddenFor(model => model.Parent.ChildOne.Id)
@Html.TextBoxFor(model => model.Parent.ChildOne.Name)
@Html.DropDownListFor(model => model.Parent.ChildOne.OptionId, Model.Options)
</div>
<div id="ChildTwo">
@Html.HiddenFor(model => model.Parent.ChildTwo.Id)
@Html.TextBoxFor(model => model.Parent.ChildTwo.Name)
@Html.DropDownListFor(model => model.Parent.ChildTwo.OptionId, Model.Options)
</div>
</div>
<input id="SaveButton" type="button" value="save" />
<script type="text/javascript">
$('#SaveButton').click(function () {
var data = $('input, select, textarea').serialize();
$.post('@Url.Action("Save")', data, function () { });
});
</script>
答案 0 :(得分:3)
是的,你做得对。使用Web应用程序中的分离实体时,您必须告诉EF每个实体的确切状态。在您的方案中,您将首先致电:
db.Entry(parent).State = EntityState.Modified;
在EFv4.1中,此操作会导致parent
附加到上下文。调用SaveChanges
时,只能将附加实体持久保存到数据库。实体的状态设置为已修改,因此上下文将在持久化实体时尝试更新数据库中的现有记录。当您调用该语句时,还会发生一件更重要的事情:所有相关实体也会附加,但它们的状态设置为不变。您必须手动设置所有相关实体的正确状态,因为EF不知道哪个是新的,已修改或已删除。这就是为什么你的以下电话也是正确的。
编辑:
请注意,这会更新父级和子级中的值,但不会更新关系本身。如果您将一个孩子与另一个孩子交换,则在使用independent associations时,该过程会复杂得多。