ASP.NET MVC3 Code-First Error - попытка обновить объект - PullRequest
3 голосов
/ 16 мая 2011

Я проверил этот вопрос и, похоже, он связан с тем, что мне нужно, но не дает точного ответа.

У меня есть объект (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к типу данных datetime и т. д. и т. д.,)

Когда я пошагово выполняю код, кажется, что мои свойства 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 увидеть дату, которая уже установлена ​​в БД (поэтому он не пытается обновить CreatedDate до 1/1/ 0001) без нарушения параллелизма?

Редактировать Хорошо ... Я нашел это.Я, по-видимому, искал @Html.HiddenFor(model => model.[property]) и все равно добавил редактор в представление.Мне это кажется немного глупым и обходным, но это работает без необходимости добавлять пользовательский код для отсоединения одного объекта и замены обновленного.

Ответы [ 2 ]

15 голосов
/ 16 мая 2011

Короткий ответ: вы уже загрузили объект в контекст с 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");
}
0 голосов
/ 16 мая 2011

Если поля CreateDate и CreatedBy отсутствуют в форме редактирования, объект действия обновления не будет иметь значений в БД.

Дополнительного вызова к БД и сбросу, как описывает ответ Эда, можно избежать, если вы включите эти поля в форму редактирования.Затем обычная модель привязки должна забрать их и вернуть вам при обновлении.

...