简体   繁体   中英

ASP.NET MVC3 Code-First Error- attempting to update entity

I've checked this question and it seems to be related to what I need, but does not answer it exactly.

I have an entity (Sql Compact using EF Code First via MVC3- if that wasn't clear from the title) for an "Issue" (generic issue tracking, just for my own education understanding of how MVC3 works). The Issue class has a CreatedBy property (Int reference to a User who Created the Issue) and a CreatedDate property (DateTime). When I use the scaffolded code to update (modified only to prevent some updated date fields from being modified by the user):

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

I receive the error mentioned in the linked question (conversion of a datetime2 data type to a datetime data type etc., etc.,)

When I step through the code, it appears my CreatedBy and CreatedDate properties are not contained in the instance of issue that the controller is passing around. When I try to fix that by grabbing another copy of the issue from the db, and updating those to values:

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

I get the concurrency violation: An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.

So, how do I get EF to see the date which is already set in the DB (so it doesn't try to update the CreatedDate to 1/1/0001) without violating concurrency?

Okay... I found it. 好的......我找到了。 I was, apparently, looking for @Html.HiddenFor(model => model.[property]) and adding the editor to the view anyway. That seems a little silly and round-about to me, but it does work without having to add custom code to detach one object and substitute an updated one.

The short answer is that you've already loaded the entity into the context with the Find and you cannot later attach another one.

You are left with two options:

  • Detach the first instance, then attach the second
  • Copy the fields from the second instance to the first

I'll share code for the first option. First, add a Detach method to your DbContext implementation:

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

Then call Detach instead of setting the variable to 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");
}

If the CreateDate and CreatedBy fields are not in the edit form, the update action object will not have the db values.

The additional call to the db and resetting, as Ed's answer describes, can be avoided if you include those fields in the edit form. Then the normal model binding should pick them up and give them back to you on the update.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM