Entity Framework может отслеживать изменения только для объектов, которые прикреплены к контексту. Объекты, созданные контекстом, автоматически присоединяются к контексту, который их создает. Поскольку объект, который вы получаете, создается MVC, Entity Framework не знает, какие значения были обновлены, а какие нет.
Есть несколько приемов, которые вы можете использовать, чтобы сообщить Entity Framework, что элемент был изменен. Один из них - извлечь объект из контекста, установить измененные значения для этого объекта, привязанного к контексту, а затем сохранить изменения. Другой способ - сделать что-то вроде этого, чтобы явно указать ObjectStateManager контекста, что некоторые свойства изменились:
/// <summary>
/// Reattach and mark specific fields on the entity as modified.
/// </summary>
/// <param name="objectContext">The context to attach the entity object.</param>
/// <param name="setName">The string representation of the set that should contain the given entity object.</param>
/// <param name="entity">The detached entity object.</param>
/// <param name="modifiedFields">Names of fields that have been modified.</param>
public static void AttachAsModified(this ObjectContext objectContext, string setName, object entity,
IEnumerable<String> modifiedFields)
{
objectContext.AttachTo(setName, entity);
ObjectStateEntry stateEntry = objectContext.ObjectStateManager.GetObjectStateEntry(entity);
foreach (String field in modifiedFields)
{
stateEntry.SetModifiedProperty(field);
}
}
Моя команда закончила разработку инфраструктуры, которая автоматически загружает объект из контекста, выясняет, какие свойства отличаются от нового, который был передан, и устанавливает эти свойства в значения, предоставленные неприкрепленным объектом. Этот подход может быть полезным для вас. Существует небольшая вероятность того, что что-то вроде AutoMapper может быть сделано для вас, но я не уверен.
Редактировать
Shea упоминает, что использует метод контроллера UpdateModel
, чтобы эффективно откладывать установку значений свойств до тех пор, пока вы не получите объект сущности из своего контекста. Это звучит так же хорошо, как и любой другой подход ко мне (при условии, что у вас все в порядке с кодом доступа к данным в вашем контроллере), но вы можете использовать переопределение, чтобы сделать так, чтобы у вас все еще была возможность привязать метод к тому же тип объекта:
[HttpPost]
public ViewResult EditBlogPost(BlogPost blogPost)
{
//This one is where I'm having issues. When model binding populates blogPost, is it auto-tracking still? For some reason SaveChanges() doesn't seem to persist the updates.
if (!ModelState.IsValid)
return View("ManageBlogPost");
var dbPost = db.BlogPosts.Single(bp => bp.BlogPostId = blogPost.Id);
UpdateModel(dbPost, "blogPost");
db.SaveChanges();
ViewData["message"] = "Blog post edited successfully.";
return View("Result");
}