简体   繁体   English

更新实体,所有更改均不保存

[英]Updating entity, all changes not saving

I have searched for this topic, and I realize there is a slightly related question here , and while the problem sounds very similar, the accepted solution did not work (which, if one reads the comments, one will know that the problem wasn't really solved). 我搜索了这个话题,我意识到有一个略微相关的问题在这里 ,虽然这个问题听起来很相似,接受的解决方案没有工作(其中,如果读取的意见,人会知道,这个问题是不是真的解决了)。

Here is my problem, and I hope someone can help: 这是我的问题,希望有人能提供帮助:

I have an Entity: 我有一个实体:

public class Garden
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual PlantHardinessZone Zone { get; set; }
}

It has a relationship with PlantHardinessZone Entity: 它与PlantHardinessZone实体有关系:

public class PlantHardinessZone
{
    public int Id { get; set; }
    public string Zone { get; set; }
}

In order to easily use the Zones in a DropDownListFor, I created a ViewModel: 为了轻松使用DropDownListFor中的区域,我创建了一个ViewModel:

public class GardenViewModel
{
    public int ZoneId { get; set; }
    public IEnumerable<PlantHardinessZone> Zones { get; set; }

    public Garden Garden { get; set; }
}

This ViewModel is used in several views. 此ViewModel在多个视图中使用。 It currently works as expected for Creating a new Garden entity, however, Editing is not functioning correctly. 目前,它可以按预期的方式用于创建新的Garden实体,但是,“编辑”无法正常运行。 If I change the Zone, it is not updated in the DB. 如果更改区域,则不会在数据库中更新区域。 I have stepped through the code, and the correct Zone information is returning from the View, it is just not updating. 我已逐步完成代码,并且正确的Zone信息是从View返回的,只是没有更新。 If I change the name of the Garden, that updates fine. 如果我更改花园的名称,则可以更新。

Here is the [HttpPost} Edit Action: 这是[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);
    }

And here is the corresponding View: 这是对应的视图:

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

Can anyone help direct me to solving this very annoying issue? 谁能帮助我解决这个非常烦人的问题? All input welcome and appreciated. 欢迎所有意见。 Thank you so much! 非常感谢!

You are setting the state of Garden to Modified but that does not have any effect on the navigation properties (the link to Zone ). 您将“ 花园”的状态设置为“已Modified但这对导航属性(指向Zone的链接)没有任何影响。 Thus EF will update only Garden , with no effect on the linked Zone . 因此,EF将仅更新Garden ,而不会影响链接的区域

If, however, you assign the Zone by it's ID , to garden.ZoneId , that will work. 但是,如果您通过其IDZone分配给garden.ZoneId ,那将起作用。 garden.ZoneId is a direct property of Garden and it will get everything properly linked. garden.ZoneIdGarden的直接财产,它将使所有内容正确链接。

garden.ZoneId = db.Zones.Where(z => z.Id == viewModel.ZoneId).Single().Id;

To recapitulate: 概括一下:
- garden.Zone is not a true property of the object, it's just a link handled behind the scenes by EF. garden.Zone 不是对象的真实属性 ,它只是EF在后台处理的链接。 This is why it fails updating. 这就是为什么更新失败。
- garden.ZoneId is a true property of the object, thus it get's updated properly if you change it. garden.ZoneId 对象的真实属性 ,因此,如果更改它,它将正确更新。

db.Gardens.Attach(garden); attaches only the garden object. 仅附加garden对象。 It doesn't attach the other objects that might be linked to it. 它不附加可能链接到它的其他对象。

Additionally I would recommend to first attach the entity to the context and then change it's properties and state. 另外,我建议先将实体附加到上下文,然后再更改其属性和状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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