简而言之,在POST包装模型并将将一个条目的状态更改为“已修改”的过程中会引发异常。在更改状态之前,将状态设置为“已分离”,但调用Attach()确实会引发相同的错误。我正在使用EF6。
请在下面找到我的代码(型号名称已更改,以便于阅读)
模型
// Wrapper classes
public class AViewModel
{
public A a { get; set; }
public List<B> b { get; set; }
public C c { get; set; }
}
控制者
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
if (!canUserAccessA(id.Value))
return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
var aViewModel = new AViewModel();
aViewModel.A = db.As.Find(id);
if (aViewModel.Receipt == null)
{
return HttpNotFound();
}
aViewModel.b = db.Bs.Where(x => x.aID == id.Value).ToList();
aViewModel.Vendor = db.Cs.Where(x => x.cID == aViewModel.a.cID).FirstOrDefault();
return View(aViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(AViewModel aViewModel)
{
if (!canUserAccessA(aViewModel.a.aID) || aViewModel.a.UserID != WebSecurity.GetUserId(User.Identity.Name))
return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
if (ModelState.IsValid)
{
db.Entry(aViewModel.a).State = EntityState.Modified; //THIS IS WHERE THE ERROR IS BEING THROWN
db.SaveChanges();
return RedirectToAction("Index");
}
return View(aViewModel);
}
如上线所示
db.Entry(aViewModel.a).State = EntityState.Modified;
引发异常:
附加类型“ A”的实体失败,因为相同类型的另一个实体已经具有相同的主键值。如果图形中的任何实体具有冲突的键值,则使用“附加”方法或将实体的状态设置为“不变”或“修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,请使用“添加”方法或“已添加”实体状态来跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。
是否有人在我的代码中看到任何错误,还是了解在什么情况下在编辑模型时会引发此类错误?
问题解决了!
Attach
该方法可能会对某人有所帮助,但在这种情况下将无济于事,因为在将文档加载到Edit GET控制器功能中时已经对其进行了跟踪。附加将引发完全相同的错误。
我在这里遇到的问题是由canUserAccessA()
在更新对象a的状态之前加载A实体的函数引起的。这正在破坏被跟踪的实体,并且正在将对象的状态更改为Detached
。
解决方案是进行修改,canUserAccessA()
以便不会跟踪我正在加载的对象。AsNoTracking()
查询上下文时应调用函数。
// User -> Receipt validation
private bool canUserAccessA(int aID)
{
int userID = WebSecurity.GetUserId(User.Identity.Name);
int aFound = db.Model.AsNoTracking().Where(x => x.aID == aID && x.UserID==userID).Count();
return (aFound > 0); //if aFound > 0, then return true, else return false.
}
由于某些原因,我无法.Find(aID)
与之配合使用,AsNoTracking()
但这并不重要,因为我可以通过更改查询来实现相同的目的。
希望这会帮助任何有类似问题的人!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句