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

时间:2011-05-16 19:29:59

标签: c# asp.net asp.net-mvc-3 sql-server-ce

我已经检查了this question,它似乎与我需要的内容有关,但并没有完全回答。

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

        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])并将编辑器添加到视图中。这对我来说似乎有点愚蠢和圆润,但它确实有效,无需添加自定义代码来分离一个对象并替换更新的对象。

2 个答案:

答案 0 :(得分:15)

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

您有两种选择:

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

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

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");
}

答案 1 :(得分:0)

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

如果您在编辑表单中包含这些字段,可以避免对Ed进行额外调用并重置,如Ed的答案所述。然后,正常的模型绑定应该接收它们并在更新时将它们返回给您。