简体   繁体   English

在实体框架中编辑对象并将其保存到ASP.NET MVC 2.0中的数据库中

[英]Editing an object in entity framework and saving it to the database in ASP.NET MVC 2.0

So I know that EF entities track their own changes and persist them to the database when savechanges is called, but what about this scenario... 所以我知道EF实体跟踪他们自己的更改并在调用savechanges时将它们保存到数据库中,但是这个场景呢......

I have a page that is designed to edit a blog post. 我有一个旨在编辑博客文章的页面。 It has two action methods. 它有两种动作方法。

    [HttpGet]
    public ViewResult EditBlogPost(int Id)
    {
        //This action method gets the blog post by the id and returns the edit blog post page.
        BlogPost blogPost = db.BlogPosts.Where(x => x.Id == Id).FirstOrDefault();
        if (blogPost == null)
        {
            ViewData["message"] = "Blog post not found.";
            return View("Result");
        }
        return View("ManageBlogPost", blogPost);
    }

    [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");
        db.AttachTo("BlogPosts", blogPost); //I tried this method, it seemed to be what I wanted, but it didn't help.
        db.SaveChanges();
        ViewData["message"] = "Blog post edited successfully.";
        return View("Result");
    }

Here is the view that these return: 以下是这些回归的观点:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Master.Master" Inherits="System.Web.Mvc.ViewPage<BlogProject.Models.BlogPost>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">

    <% if (Model != null)
       { %>
            <h2>Edit Blog Post</h2>
    <% }
       else
       { %>
            <h2>Add Blog Post</h2>
    <% } %>
    <% using (Html.BeginForm())
       { %>
            <% if (Model != null)
               { %>
                    <%: Html.HiddenFor(x => x.Id)%> <!-- Is this the way to keep un-editable data hidden from the edit form and have them repopulate on the next model bind? What if someone went to modify their POST using something like Fiddler? Couldn't they theoretically edit these fields before the POST? -->
                    <%: Html.HiddenFor(x => x.Date) %>
                    <%: Html.HiddenFor(x => x.Author) %>
                    <%: Html.HiddenFor(x => x.FriendlyUrl) %>
            <% } %>
            Title:<br />
            <%: Html.TextBoxFor(x => x.Title, new { Style = "Width: 90%;" })%>
            <br />
            <br />
            Summary:<br />
            <%: Html.TextAreaFor(x => x.Summary, new { Style = "Width: 90%; Height: 50px;" }) %>
            <br />
            <br />
            Body:<br />
            <%: Html.TextAreaFor(x => x.Body, new { Style = "Height: 250px; Width: 90%;" })%>
            <br />
            <br />
            <input type="submit" value="Submit" />
    <% } %>

</asp:Content>

I'm a little confused here. 我在这里有点困惑。 Adding blog posts seems to work fine, but editing them is another story. 添加博客文章似乎工作正常,但编辑它们是另一个故事。

The solution is not to take in the blog post object in your edit action method. 解决方案不是在编辑操作方法中接受博客文章对象。 Instead, do something that looks like this: 相反,做一些看起来像这样的事情:

[HttpPost]
public ViewResult EditBlogPost(int postID)
{
    var post = db.BlogPosts.Single(p => p.PostID = postID);
    TryUpdateModel(post);

    if (!ModelState.IsValid)
        return View("ManageBlogPost");

    db.SaveChanges();

    ViewData["message"] = "Blog post edited successfully.";
    return View("Result");
}

This way the object is attached to the context and the EF can track changes properly. 这样,对象附加到上下文,EF可以正确跟踪更改。 The UpdateModel method is a time saver that automatically matches fields in the form collection to the fields in the model and updates them for you. UpdateModel方法是一个节省时间的方法,可以自动将表单集合中的字段与模型中的字段进行匹配,并为您更新它们。

Here is the documentation for UpdateModel : MSDN 以下是UpdateModel的文档: MSDN

Entity Framework is only able to track changes on objects that are attached to a context. 实体框架只能跟踪附加到上下文的对象的更改。 Objects produced by a context are automatically attached to the context that produces them. 上下文生成的对象会自动附加到生成它们的上下文中。 Since the object you're getting is produced by MVC, the Entity Framework doesn't know which values have been updated and which haven't been. 由于您获取的对象是由MVC生成的,因此实体框架不知道哪些值已更新,哪些值尚未更新。

There are a couple of tricks you can use to tell Entity Framework that the item has been modified. 您可以使用几个技巧告诉Entity Framework该项目已被修改。 One is to retrieve the entity from the context, set the changed values on that context-bound object, and then save your changes. 一种是从上下文中检索实体,在该上下文绑定对象上设置更改的值,然后保存更改。 Another is to do something like this to explicitly tell the context's ObjectStateManager that certain properties have changed: 另一个是做这样的事情来明确地告诉上下文的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);
        }
    }

My team ended up developing a framework that automatically loads the object from the context, figures out which properties are different from the new one that got passed in, and sets those properties to the values provided by the unattached object. 我的团队最终开发了一个框架,该框架自动从上下文加载对象,找出哪些属性与传入的新属性不同,并将这些属性设置为未附加对象提供的值。 That approach may be worth looking into for you as well. 这种方法也值得为您考虑。 There is a slight possibility that something like AutoMapper could be made to do this for you, but I'm not sure. 有可能像AutoMapper这样的东西可以为你做这件事,但我不确定。

Edit 编辑

Shea mentions using the controller's UpdateModel method to effectively put off the setting of the property values until after you have retrieved the entity object from your context. Shea提到使用控制器的UpdateModel方法有效地推迟了属性值的设置,直到从上下文中检索实体对象为止。 This sounds like as good an approach as any to me (assuming you're okay with having data-access code in your controller), but you may want to use an override to make it so you can still have the method bind to the same object type: 这对我来说听起来像是一个好方法(假设你在控制器中有数据访问代码就可以了),但是你可能想要使用覆盖来实现它,这样你仍然可以让方法绑定到同一个对象类型:

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

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

相关问题 使用 asp.net mvc 4 + Entity Framework 将图像保存到数据库 - Saving images to database with asp.net mvc 4 + Entity Framework 努力使用实体框架将数据保存到ASP.NET MVC中的数据库 - Struggling with saving data to database in ASP.NET MVC with Entity Framework 带有ASP.NET MVC的实体框架将值保存到错误的列 - Entity Framework with ASP.NET MVC is saving value to wrong column 在ASP.NET MVC(实体框架)中将JSON数据对象存储到数据库 - Store JSON data object to database in ASP.NET MVC (Entity Framework) PopUp 不在 ASP.NET MVC 5 和实体框架中的数据库中发送数据 - PopUp not sending data in database in ASP.NET MVC 5 and Entity Framework ASP.net MVC与Entity Framework重新排序数据库记录 - ASP.net MVC with Entity Framework reordering database records ASP.NET MVC 4实体框架数据库第一个存储库 - ASP.NET MVC 4 Entity Framework Database First Repository 配方-Entity Framework ASP.NET MVC中的成分数据库 - Recipe - ingredients database in Entity Framework ASP.NET MVC Entity Framework Core 和 ASP.NET Core MVC 中的 Inheritance 数据库 - Inheritance Database in Entity Framework Core and ASP.NET Core MVC 没有实体框架数据库连接的ASP.NET MVC - ASP.NET MVC without Entity Framework database connection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM