Bearbeiten Sie ein Objekt im entity-framework und dem speichern auf der Datenbank in ASP.NET MVC 2.0
Also ich weiß, dass EF-Einheiten verfolgen Ihre eigenen änderungen und speichern Sie zur Datenbank, wenn savechanges aufgerufen wird, aber was ist mit diesem Szenario...
Ich habe eine Seite, die ist so konzipiert, Bearbeiten Sie einen blog-post. Es hat zwei action-Methoden.
[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");
}
Hier ist der Ansicht, dass diese Rückkehr:
<%@ 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>
Ich bin ein wenig verwirrt hier. Hinzufügen von blog-posts scheint zu funktionieren, aber Sie zu Bearbeiten, ist eine andere Geschichte.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Lösung ist, nicht in der blog-post-Objekt in der edit-Aktion-Methode. Stattdessen machen Sie etwas, das wie folgt aussieht:
Diese Weise das Objekt verbunden ist, um den Kontext und die EF kann änderungen verfolgen, richtig. Die
UpdateModel
Methode ist eine Zeitersparnis, die automatisch die passenden Felder in der form-Auflistung, um die Felder in das Modell ein und aktualisiert Sie für Sie.Hier ist die Dokumentation für
UpdateModel
:MSDN
TryUpdateModel(post)
sollte verwendet werden, und Sie beide und die LINQ-Abfrage sollte vor derif(!ModelState.IsValid)
Linie.TryUpdateModel()
keine Ausnahme auslöst, wenn das Modell ungültig ist, wodurch dieif
Anweisung zu fangen, die Rückkehr der Sicht mit der Validierung Helfer.UpdateModel()
undTryUpdateModel()
den Standardwert verwenden, der Anbieter, was bedeutet, dass das argumentFormCollection collection
ist nicht nötig, da es automatisch verwendetRequest.Form
Sammlung als it ' s Wert Anbieter. Jedoch werden sowohl die get-und post-action-Methoden können nicht akzeptieren, die gleichen Argumente, so dass Sie ändern müssen, um die Signatur der Methode in gewisser Weise. Ich entschied mich für ändern Sie den Namen der Methode, und stellen Sie dann die form in den Blick rufen Sie den neuen Namen ein. Scheint besser als das hinzufügen ein argument, nur so die Unterschriften sind nicht die gleichen.Entity Framework ist nur in der Lage, die änderungen zu verfolgen, die auf Objekten angebracht sind, um ein Kontext. Objekte, die von einem Kontext, werden automatisch an den Kontext, die Sie produziert. Da das Objekt, das Sie bekommen wird hergestellt von MVC, Entity Framework nicht weiß, welche Werte aktualisiert wurden und welche nicht.
Gibt es ein paar tricks, die Sie verwenden können, um sagen, Entity Framework, dass das Element geändert wurde. Ist man zum abrufen der Entität aus dem Kontext, setzen Sie die geänderten Werte der context-bound-Objekt, und speichern Sie dann Ihre änderungen. Ein anderes ist, so etwas zu tun, um explizit zu sagen, der Kontext ist ObjectStateManager, die bestimmte Eigenschaften haben sich geändert:
Mein team endete der Entwicklung eines Rahmens, der automatisch lädt das Objekt aus dem Kontext, findet heraus, welche Eigenschaften unterscheiden sich von den neuen, die habe bestanden, und setzt die Eigenschaften auf die Werte, die Ihnen das ungebundene Objekt. Dieser Ansatz kann sein, lohnt ein Blick in für Sie als gut. Es ist eine leichte Möglichkeit, dass so etwas wie AutoMapper hergestellt werden könnte, dies für Sie tun, aber ich bin mir nicht sicher.
Bearbeiten
Shea erwähnt mit dem controller ist
UpdateModel
Methode, um effektiv stellen Sie die Einstellung der Eigenschaft Werte erst auf, nachdem Sie Sie abgerufen haben das entity-Objekt aus Ihrem Kontext. Das klingt so gut, ein Ansatz, wie jeder zu mir (vorausgesetzt, du bist okay, mit Daten-Zugangs-code in Ihr controller), aber Sie verwenden möchten, können Sie ein override zu machen, so dass Sie immer noch die Methode bind, um die gleiche Objekt-Typ: