Я искал эту тему, и я понимаю, что есть немного связанный вопрос here, и хотя проблема звучит очень похоже, принятое решение не работает (что, если читать комментарии , то будет известно, что проблема на самом деле не решена).Обновление объекта, все изменения не сохраняются
Вот моя проблема, и я надеюсь, что кто-то может помочь:
У меня есть Entity:
public class Garden
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual PlantHardinessZone Zone { get; set; }
}
Она имеет отношения с PlantHardinessZone Entity:
public class PlantHardinessZone
{
public int Id { get; set; }
public string Zone { get; set; }
}
Для того, чтобы легко использовать зоны в DropDownListFor, я создал ViewModel:
public class GardenViewModel
{
public int ZoneId { get; set; }
public IEnumerable<PlantHardinessZone> Zones { get; set; }
public Garden Garden { get; set; }
}
Эта модель ViewModel используется в нескольких представлениях. В настоящее время он работает так, как ожидалось, для создания нового объекта Garden, однако редактирование работает неправильно. Если я изменю Зону, она не будет обновлена в БД. Я прошел через код, и правильная информация о зоне возвращается из представления, она просто не обновляется. Если я изменю имя сада, это будет прекрасно.
Вот [HttpPost} Редактировать Действие:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(GardenViewModel viewModel)
{
if (ModelState.IsValid)
{
Garden garden = viewModel.Garden;
garden.Zone = db.Zones.Where(z => z.Id == viewModel.ZoneId).Single();
db.Gardens.Attach(garden); // per the solution accepted [here][2]
db.Entry(garden).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
А вот соответствующий вид:
@model GardenManager.Web.ViewModels.GardenViewModel
@{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Garden</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Garden.Id)
<div class="form-group">
@Html.LabelFor(model => model.Garden.Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Garden.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Garden.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-10 col-md-offset-2">
@Html.DropDownListFor(model => model.ZoneId,
new SelectList(Model.Zones, "Id", "Zone", Model.ZoneId),
"Select Zone", new { @class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Может кто-нибудь помочь направить меня к решению этой очень раздражает вопрос? Весь вход приветствуется и оценивается. Спасибо огромное!
'db.Вход (сад) .State = EntityState.Modified' отмечает только «сад», а не его навигационные свойства. Вот что вызывает ваше замешательство. Использование EF в отключенной среде не так просто, как должно быть. Вы должны пройти весь график объекта, чтобы получить все изменения в трекере изменений. Существует библиотека, [Graphdiff] (https://github.com/refactorthis/GraphDiff), которая может выполнить эту задачу для вас. –
Мое замешательство приходит, потому что в моей голове Зона менялась, только FK в саду указывала на соответствующую Зону. В соответствии с ответом я добавил явный FK (ZoneId) и обновление, которое работало так, как я ожидал. :) – OCDDev