在我的mvc应用程序中,我有很多相关数据,我需要编写一个方法来允许编辑/更新相关数据,此时我的数据是使用ViewModel处理的。我试图写一个方法来做到这一点,但我不能让它正常工作,我不确定我的方法是否正确,所以我想得到一些指导。
这是我的代码:
控制器代码
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(FullVesselViewModel model)
{
var vessel = new tbl_vessels
{
vessel_idx = model.vessel_idx,
vessel_name = model.vessel_name
};
var vessel_spec = new tbl_vessel_spec
{
spec_idx = model.spec_idx,
bhp = model.bhp
}
using (var context = new dataEntities())
{
context.Entry(vessel).State = EntityState.Modified;
context.Entry(vessel_spec).State = EntityState.Modified;
context.SaveChanges();
return RedirectToAction("Index");
}
}
我最初的做法是声明我的viewmodel,然后分解两个相关实体并将它们存储在变量中,将这些变量命名为已修改,然后保存我的更改。我的上述方法返回并发错误。我已将实体的索引存储在几个隐藏的字段中,以查看是否有帮助,但我没有运气。
查看
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.vessel_idx)
@Html.HiddenFor(model => model.spec_idx)
...input fields etc ...
}
我的想法是否适用于这种情况,还是我过度设计了一些可以做得更简单的事情?
我得到的错误如下,并在SaveChanges()中触发:
Entity Framework: “Store update, insert, or delete statement affected an unexpected number of rows (0).”
答案 0 :(得分:0)
分析您的代码后&发现context.SaveChanges()
作为EF异常的来源,您可以选择适合您的问题的其中一种解决方案。
在保存更改之前将EntityState
更改为Added
:
using (var context = new dataEntities())
{
context.Entry(vessel).State = EntityState.Added;
context.Entry(vessel_spec).State = EntityState.Added;
context.SaveChanges();
return RedirectToAction("Index");
}
或在找到数据匹配后在控制器操作中使用TryUpdateModel
,以防您需要更新数据而不更改主键:
var foundvessel = context.tbl_vessels.Where(x => x.vessel_idx == model.vessel_idx).FirstOrDefault();
var foundvspec = context.tbl_vessel_spec.Where(x => x.spec_idx == model.spec_idx).FirstOrDefault();
if (foundvessel != null && foundvspec != null)
{
var vessel = new tbl_vessels
{
vessel_idx = model.vessel_idx,
vessel_name = model.vessel_name
};
var vessel_spec = new tbl_vessel_spec
{
spec_idx = model.spec_idx,
bhp = model.bhp
}
using (var context = new dataEntities())
{
this.TryUpdateModel(vessel);
this.TryUpdateModel(vessel_spec);
context.SaveChanges();
return RedirectToAction("Index");
}
}
EF生成的错误表示一个乐观的并发异常,您尝试更新某些表的主键值,即vessel_idx
& spec_idx
是每个目标表的主键,EF将其修改为添加新行,而不是针对现有数据进行更新。
因此,您需要执行:
EntityState.Added
如果已添加新主键
EntityState.Modified
如果现有主键保持不变
欢迎任何改进或建议。