ASP.NET MVC3代码优先错误 – 尝试更新实体

我已经检查了这个问题 ,它似乎与我需要的东西有关,但并没有完全回答。

我有一个实体(Sql Compact使用EF Code First通过MVC3-如果标题不清楚的话)“问题”(通用问题跟踪,只是为了我自己的教育理解MVC3如何工作)。 Issue类具有CreatedBy属性(对创建问题的用户的Int引用)和CreatedDate属性(DateTime)。 当我使用scaffolded代码进行更新时(仅修改以防止某些更新的日期字段被用户修改):

if (ModelState.IsValid) { issue.LastActivity = (DateTime?)DateTime.Now.Date; if (issue.ClosedBy != null) issue.ClosedDate = (DateTime?)DateTime.Now.Date; startingIssue = null; db.Entry(issue).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } 

我收到链接问题中提到的错误(将datetime2数据类型转换为日期时间数据类型等等)

当我单步执行代码时,看起来我的CreatedBy和CreatedDate属性不包含在控制器传递的issue实例中。 当我尝试通过从数据库中获取问题的另一个副本并将其更新为值来解决此问题时:

  var startingIssue = db.Issues.Find(issue.IssueId); if (ModelState.IsValid) { if (issue.CreatedBy != startingIssue.CreatedBy) issue.CreatedBy = startingIssue.CreatedBy; if (issue.CreatedDate != startingIssue.CreatedDate) issue.CreatedDate = startingIssue.CreatedDate; issue.LastActivity = (DateTime?)DateTime.Now.Date; if (issue.ClosedBy != null) issue.ClosedDate = (DateTime?)DateTime.Now.Date; startingIssue = null; db.Entry(issue).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } 

我得到并发冲突:ObjectStateManager中已经存在具有相同密钥的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。

那么,如何在不违反并发性的情况下让EF查看已在DB中设置的日期(因此它不会尝试将CreatedDate更新为1/1/0001)?

编辑好的……我找到了。 显然,我正在寻找@Html.HiddenFor(model => model.[property])并将编辑器添加到视图中。 这对我来说似乎有点愚蠢和圆润,但它确实有效,无需添加自定义代码来分离一个对象并替换更新的对象。

简短的回答是,您已经使用“ Find将实体加载到上下文中,之后无法附加另一个实体。

你有两个选择:

  • 分离第一个实例,然后附加第二个实例
  • 将字段从第二个实例复制到第一个实例

我会分享第一个选项的代码。 首先,在DbContext实现中添加一个Detach方法:

 public void Detach(object entity) { var objectContext = ((IObjectContextAdapter)this).ObjectContext; objectContext.Detach(entity); } 

然后调用Detach而不是将变量设置为null

 var startingIssue = db.Issues.Find(issue.IssueId); if (ModelState.IsValid) { if (issue.CreatedBy != startingIssue.CreatedBy) issue.CreatedBy = startingIssue.CreatedBy; if (issue.CreatedDate != startingIssue.CreatedDate) issue.CreatedDate = startingIssue.CreatedDate; issue.LastActivity = (DateTime?)DateTime.Now.Date; if (issue.ClosedBy != null) issue.ClosedDate = (DateTime?)DateTime.Now.Date; // startingIssue = null; db.Detach(startingIssue); db.Entry(issue).State = EntityState.Modified; db.SaveChanges(); return RedirectToAction("Index"); } 

如果CreateDate和CreatedBy字段不在编辑表单中,则更新操作对象将不具有db值。

如Ed的回答所描述的,如果在编辑表单中包含这些字段,则可以避免对数据库和重置的附加调用。 然后,正常的模型绑定应该将它们拾取并在更新时将它们返回给您。