Hinzufügen eines neuen Felds

von Rick Anderson

Hinweis

Eine aktualisierte Version dieses Tutorials ist hier mit der neuesten Version von Visual Studio verfügbar. Im neuen Tutorial wird ASP.NET Core MVC verwendet, der viele Verbesserungen gegenüber diesem Tutorial bietet.

Dieses Tutorial vermittelt Informationen zu ASP.NET Core MVC mit Controllern und Ansichten. Razor Pages ist eine neue Alternative in ASP.NET Core, einem seitenbasierten Programmiermodell, das das Erstellen der Webbenutzeroberfläche vereinfacht und produktiver macht. Es empfiehlt sich, dass Sie sich das Tutorial der Razor Pages vor der MVC-Version ansehen. Das Tutorial zu Razor Pages:

  • Ist einfacher zu befolgen.
  • Behandelt mehr Features.
  • Ist der bevorzugte Ansatz für die Entwicklung neuer Apps.

In diesem Abschnitt verwenden Sie Entity Framework Code First-Migrationen, um einige Änderungen an den Modellklassen zu migrieren, damit die Änderung auf die Datenbank angewendet wird.

Wenn Sie entity Framework Code First verwenden, um automatisch eine Datenbank zu erstellen, wie weiter oben in diesem Tutorial, fügt Code First der Datenbank eine Tabelle hinzu, um nachzuverfolgen, ob das Schema der Datenbank mit den Modellklassen synchronisiert ist, aus denen es generiert wurde. Wenn sie nicht synchronisiert sind, löst Entity Framework einen Fehler aus. Dies erleichtert das Auffinden von Problemen zur Entwicklungszeit, die Sie andernfalls nur zur Laufzeit (durch obskure Fehler) finden.

Einrichten von Code First-Migrationen für Modelländerungen

Navigieren Sie zu Projektmappen-Explorer. Klicken Sie mit der rechten Maustaste auf die Datei Movies.mdf , und wählen Sie Löschen aus, um die Filmdatenbank zu entfernen. Wenn die Datei Movies.mdf nicht angezeigt wird, klicken Sie in der roten Gliederung unten auf das Symbol Alle Dateien anzeigen .

Screenshot, der die Registerkarte

Erstellen Sie die Anwendung, um sicherzustellen, dass keine Fehler vorliegen.

Klicken Sie im Menü Extras auf NuGet-Paket-Manager und dann auf Paket-Manager-Konsole.

Hinzufügen von Pack Man

Geben Sie im Fenster "Paket-Manager-Konsole " an der Eingabeaufforderung ein PM> .

Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext

Screenshot: Fenster

Der Befehl Enable-Migrations (siehe oben) erstellt eine Datei Configuration.cs in einem neuen Migrationsordner .

Screenshot: Projektmappen-Explorer Der Unterordner Configuration punkt c s des Ordners Migrationen ist ausgewählt.

Visual Studio öffnet die Datei Configuration.cs . Ersetzen Sie die Seed -Methode in der Datei Configuration.cs durch den folgenden Code:

protected override void Seed(MvcMovie.Models.MovieDBContext context)
{
    context.Movies.AddOrUpdate( i => i.Title,
        new Movie
        {
            Title = "When Harry Met Sally",
            ReleaseDate = DateTime.Parse("1989-1-11"),
            Genre = "Romantic Comedy",
            Price = 7.99M
        },

         new Movie
         {
             Title = "Ghostbusters ",
             ReleaseDate = DateTime.Parse("1984-3-13"),
             Genre = "Comedy",
             Price = 8.99M
         },

         new Movie
         {
             Title = "Ghostbusters 2",
             ReleaseDate = DateTime.Parse("1986-2-23"),
             Genre = "Comedy",
             Price = 9.99M
         },

       new Movie
       {
           Title = "Rio Bravo",
           ReleaseDate = DateTime.Parse("1959-4-15"),
           Genre = "Western",
           Price = 3.99M
       }
   );
   
}

Zeigen Sie auf die rote Wellenlinie unterMovie, klicken Sie auf Show Potential Fixes MvcMovie.Models, und klicken Sie dann auf MvcMovie.Models;

Screenshot: Menü

Dadurch wird die folgende using-Anweisung hinzugefügt:

using MvcMovie.Models;

Hinweis

Code First-Migrationen ruft die Seed -Methode nach jeder Migration auf (d. h. beim Aufrufen von update-database in der Paket-Manager-Konsole), und diese Methode aktualisiert bereits eingefügte Zeilen oder fügt sie ein, wenn sie noch nicht vorhanden sind.

Die AddOrUpdate-Methode im folgenden Code führt einen Upsert-Vorgang aus:

context.Movies.AddOrUpdate(i => i.Title,
    new Movie
    {
        Title = "When Harry Met Sally",
        ReleaseDate = DateTime.Parse("1989-1-11"),
        Genre = "Romantic Comedy",
        Rating = "PG",
        Price = 7.99M
    }

Da die Seed-Methode mit jeder Migration ausgeführt wird, können Sie nicht einfach Daten einfügen, da die Zeilen, die Sie hinzufügen möchten, bereits nach der ersten Migration vorhanden sind, die die Datenbank erstellt. Der Vorgang "upsert" verhindert Fehler, die auftreten würden, wenn Sie versuchen, eine bereits vorhandene Zeile einzufügen. Er überschreibt jedoch alle Änderungen an Daten, die Sie beim Testen der Anwendung vorgenommen haben. Bei Testdaten in einigen Tabellen möchten Sie möglicherweise nicht, dass dies geschieht: In einigen Fällen, wenn Sie Daten beim Testen ändern, möchten Sie, dass ihre Änderungen nach Datenbankupdates beibehalten werden. In diesem Fall möchten Sie einen bedingten Einfügevorgang ausführen: Fügen Sie eine Zeile nur ein, wenn sie noch nicht vorhanden ist.

Der erste Parameter, der an die AddOrUpdate-Methode übergeben wird, gibt die Eigenschaft an, mit der überprüft werden soll, ob bereits eine Zeile vorhanden ist. Für die von Ihnen bereitgestellten Testfilmdaten kann die Title -Eigenschaft zu diesem Zweck verwendet werden, da jeder Titel in der Liste eindeutig ist:

context.Movies.AddOrUpdate(i => i.Title,

Bei diesem Code wird davon ausgegangen, dass Titel eindeutig sind. Wenn Sie manuell einen doppelten Titel hinzufügen, erhalten Sie die folgende Ausnahme, wenn Sie das nächste Mal eine Migration durchführen.

Sequenz enthält mehr als ein Element

Weitere Informationen zur AddOrUpdate-Methode finden Sie unter Berücksichtigen der EF 4.3 AddOrUpdate-Methode.

Drücken Sie STRG-UMSCHALT-B, um das Projekt zu erstellen.(Die folgenden Schritte schlagen fehl, wenn Sie an diesem Punkt nicht erstellen.)

Der nächste Schritt besteht darin, eine DbMigration Klasse für die erste Migration zu erstellen. Durch diese Migration wird eine neue Datenbank erstellt. Aus diesem Grund haben Sie die Datei movie.mdf in einem vorherigen Schritt gelöscht.

Geben Sie im Fenster Paket-Manager-Konsole den Befehl add-migration Initial ein, um die erste Migration zu erstellen. Der Name "Initial" ist willkürlich und wird verwendet, um die erstellte Migrationsdatei zu benennen.

Screenshot: Paket-Manager-Konsole Text im Befehl

Code First-Migrationen erstellt eine weitere Klassendatei im Migrationsordner (mit dem Namen {DateStamp}_Initial.cs ), und diese Klasse enthält Code, der das Datenbankschema erstellt. Der Name der Migrationsdatei ist vorab mit einem Zeitstempel festgelegt, um die Reihenfolge zu erleichtern. Untersuchen Sie die Datei {DateStamp}_Initial.cs . Sie enthält die Anweisungen zum Erstellen der Movies Tabelle für die Movie DB. Wenn Sie die Datenbank in den folgenden Anweisungen aktualisieren, wird diese {DateStamp}_Initial.cs-Datei ausgeführt und das Datenbankschema erstellt. Anschließend wird die Seed-Methode ausgeführt, um die Datenbank mit Testdaten aufzufüllen.

Geben Sie in der Paket-Manager-Konsole den Befehl update-database ein, um die Datenbank zu erstellen, und führen Sie die Seed -Methode aus.

Screenshot: Paket-Manager-Konsole Der Befehl

Wenn Sie eine Fehlermeldung erhalten, die angibt, dass eine Tabelle bereits vorhanden ist und nicht erstellt werden kann, liegt dies wahrscheinlich daran, dass Sie die Anwendung ausgeführt haben, nachdem Sie die Datenbank gelöscht haben und bevor Sie ausgeführt haben update-database. Löschen Sie in diesem Fall erneut die Datei Movies.mdf , und wiederholen Sie den update-database Befehl. Wenn sie weiterhin einen Fehler erhalten, löschen Sie den Migrationsordner und den Inhalt, und beginnen Sie dann mit den Anweisungen oben auf dieser Seite (löschen Sie die Datei Movies.mdf , und fahren Sie dann mit Enable-Migrations fort). Wenn weiterhin ein Fehler auftritt, öffnen Sie SQL Server Objekt-Explorer, und entfernen Sie die Datenbank aus der Liste. Wenn Sie eine Fehlermeldung mit dem Hinweis erhalten, dass die MDF-Datei nicht als Datenbank angefügt werden kann, entfernen Sie die Anfänglichkatalogeigenschaft als Teil der Verbindungszeichenfolge in der web.config-Datei .

Führen Sie die Anwendung aus, und navigieren Sie zur URL /Movies . Die Startdaten werden angezeigt.

Screenshot: M V C Movie Index mit vier aufgeführten Filmen

Hinzufügen einer Rating-Eigenschaft zum Movie-Modell

Fügen Sie zunächst der vorhandenen Movie Klasse eine neue Rating Eigenschaft hinzu. Öffnen Sie die Datei Models\Movie.cs , und fügen Sie die Rating Eigenschaft wie folgt hinzu:

public string Rating { get; set; }

Die vollständige Movie Klasse sieht nun wie der folgende Code aus:

public class Movie
{
    public int ID { get; set; }
    public string Title { get; set; }

    [Display(Name = "Release Date")]
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime ReleaseDate { get; set; }
    public string Genre { get; set; }
    public decimal Price { get; set; }
    public string Rating { get; set; }
}

Erstellen Sie die Anwendung (STRG+UMSCHALT+B).

Da Sie der Movie -Klasse ein neues Feld hinzugefügt haben, müssen Sie auch die Bindungs-Zulassungsliste aktualisieren, damit diese neue Eigenschaft einbezogen wird. Aktualisieren Sie das -Attribut für Create die bind - und Edit -Aktionsmethoden, um die Rating -Eigenschaft einzuschließen:

[Bind(Include = "ID,Title,ReleaseDate,Genre,Price,Rating")]

Sie müssen auch die Ansichtsvorlagen aktualisieren, um die neue Rating-Eigenschaft in der Browseransicht anzuzeigen, zu erstellen und zu bearbeiten.

Öffnen Sie die Datei \Views\Movies\Index.cshtml, und fügen Sie direkt hinter der Spalte Price eine <th>Rating</th> Spaltenüberschrift hinzu. Fügen Sie dann am Ende der Vorlage eine <td> Spalte hinzu, um den Wert zu rendern @item.Rating . Im Folgenden sehen Sie, wie die aktualisierte Index.cshtml-Ansichtsvorlage aussieht:

@model IEnumerable<MvcMovie.Models.Movie>
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
    @Html.ActionLink("Create New", "Create")
    @using (Html.BeginForm("Index", "Movies", FormMethod.Get))
    {
    <p>
        Genre: @Html.DropDownList("movieGenre", "All")
        Title: @Html.TextBox("SearchString")
        <input type="submit" value="Filter" />
    </p>
    }
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Title)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ReleaseDate)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Genre)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Price)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Rating)
        </th>

        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ReleaseDate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Genre)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Rating)
        </td>

        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}

</table>

Öffnen Sie als Nächstes die Datei \Views\Movies\Create.cshtml , und fügen Sie das Rating Feld mit dem folgenden hervorgehobenen Markup hinzu. Dadurch wird ein Textfeld gerendert, sodass Sie beim Erstellen eines neuen Films eine Bewertung angeben können.

<div class="form-group">
            @Html.LabelFor(model => model.Price, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Rating, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Rating, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Rating, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Sie haben jetzt den Anwendungscode aktualisiert, um die neue Rating Eigenschaft zu unterstützen.

Führen Sie die Anwendung aus, und navigieren Sie zur URL /Movies . Wenn Sie dies tun, wird jedoch einer der folgenden Fehler angezeigt:

Screenshot: Fehler

Das Modell, das den MovieDBContext-Kontext hinter sich hat, hat sich seit der Erstellung der Datenbank geändert. Consider using Code First Migrations to update the database (https://go.microsoft.com/fwlink/?LinkId=238269) (Das Modell, das den Kontext „BlogContext“ unterstützt, wurde seit der Erstellung der Datenbank verändert. Verwenden Sie Code First-Migrationen, um die Datenbank zu aktualisieren).

Screenshot: Browser mit dem Benachrichtigungsserverfehler in der Anwendung

Dieser Fehler wird angezeigt, da sich die aktualisierte Movie Modellklasse in der Anwendung jetzt vom Schema der Movie Tabelle der vorhandenen Datenbank unterscheidet. (Die Datenbanktabelle enthält nicht die Spalte Rating.)

Es gibt mehrere Vorgehensweisen zum Beheben des Fehlers:

  1. Lassen Sie die Datenbank von Entity Framework automatisch löschen und basierend auf dem neuen Modellklassenschema neu erstellen. Dieser Ansatz ist früh im Entwicklungszyklus sehr praktisch, wenn die aktive Entwicklung in einer Testdatenbank erfolgt. Er ermöglicht Ihnen, das Modell und das Datenbankschema schnell weiterzuentwickeln. Der Nachteil besteht jedoch darin, dass vorhandene Daten in der Datenbank verloren gehen . Sie möchten diesen Ansatz also nicht für eine Produktionsdatenbank verwenden! Das Verwenden eines Initialisierers zum automatischen Ausführen eines Seedings für eine Datenbank mit Testdaten ist häufig eine produktive Möglichkeit zum Entwickeln einer Anwendung. Weitere Informationen zu Entity Framework-Datenbankinitialisierern finden Sie im Tutorial ASP.NET MVC/Entity Framework.
  2. Ändern Sie das Schema der vorhandenen Datenbank explizit so, dass es mit den Modellklassen übereinstimmt. Der Vorteil dieses Ansatzes ist, dass Sie Ihre Daten behalten. Sie können diese Änderung entweder manuell oder durch Erstellen eines Änderungsskripts für die Datenbank vornehmen.
  3. Verwenden Sie Code First-Migrationen, um das Datenbankschema zu aktualisieren.

Für dieses Tutorial verwenden wir Code First-Migrationen.

Aktualisieren Sie die Seed-Methode, sodass sie einen Wert für die neue Spalte bereitstellt. Öffnen Sie die Migrations\Configuration.cs-Datei, und fügen Sie jedem Movie-Objekt ein Bewertungsfeld hinzu.

new Movie
{
    Title = "When Harry Met Sally",
    ReleaseDate = DateTime.Parse("1989-1-11"),
    Genre = "Romantic Comedy",
    Rating = "PG",
    Price = 7.99M
},

Erstellen Sie die Projektmappe, öffnen Sie dann das Fenster Paket-Manager-Konsole , und geben Sie den folgenden Befehl ein:

add-migration Rating

Der add-migration Befehl weist das Migrationsframework an, das aktuelle Filmmodell mit dem aktuellen Movie DB-Schema zu untersuchen und den erforderlichen Code für die Migration der Datenbank zum neuen Modell zu erstellen. Der Name Bewertung ist willkürlich und wird verwendet, um die Migrationsdatei zu benennen. Es ist hilfreich, einen aussagekräftigen Namen für den Migrationsschritt zu verwenden.

Wenn dieser Befehl abgeschlossen ist, öffnet Visual Studio die Klassendatei, die die neue DbMigration abgeleitete Klasse definiert, und in der Up -Methode sehen Sie den Code, der die neue Spalte erstellt.

public partial class AddRatingMig : DbMigration
{
    public override void Up()
    {
        AddColumn("dbo.Movies", "Rating", c => c.String());
    }
    
    public override void Down()
    {
        DropColumn("dbo.Movies", "Rating");
    }
}

Erstellen Sie die Projektmappe, und geben Sie dann den update-database Befehl im Fenster Paket-Manager-Konsole ein.

Die folgende Abbildung zeigt die Ausgabe im Fenster "Paket-Manager-Konsole " (Der Datumsstempel vor der Bewertung unterscheidet sich.)

Screenshot: Fenster

Führen Sie die Anwendung erneut aus, und navigieren Sie zur /Movies-URL. Das neue Feld "Bewertung" wird angezeigt.

Screenshot: Liste des M V C-Filmindex mit hinzugefügtem Feld

Klicken Sie auf den Link Neu erstellen , um einen neuen Film hinzuzufügen. Beachten Sie, dass Sie eine Bewertung hinzufügen können.

7_CreateRioII

Klicken Sie auf Erstellen. Der neue Film, einschließlich der Bewertung, wird jetzt in der Filmliste angezeigt:

7_ourNewMovie_SM

Nachdem das Projekt Migrationen verwendet, müssen Sie die Datenbank nicht löschen, wenn Sie ein neues Feld hinzufügen oder das Schema anderweitig aktualisieren. Im nächsten Abschnitt nehmen wir weitere Schemaänderungen vor und verwenden Migrationen, um die Datenbank zu aktualisieren.

Sie sollten das Rating Feld auch den Ansichtsvorlagen Bearbeiten, Details und Löschen hinzufügen.

Sie könnten den Befehl "update-database" erneut im Fenster der Paket-Manager-Konsole eingeben, und es wird kein Migrationscode ausgeführt, da das Schema mit dem Modell übereinstimmt. Beim Ausführen von "update-database" wird die Seed -Methode jedoch erneut ausgeführt. Wenn Sie die Seed-Daten geändert haben, gehen die Änderungen verloren, da die Seed Methode Daten upsert. Weitere Informationen zur Seed Methode finden Sie im beliebten Tutorial ASP.NET MVC/Entity Framework von Tom Dykstra.

In diesem Abschnitt haben Sie erfahren, wie Sie Modellobjekte ändern und die Datenbank mit den Änderungen synchronisieren können. Außerdem haben Sie gelernt, wie Sie eine neu erstellte Datenbank mit Beispieldaten auffüllen können, damit Sie Szenarien ausprobieren können. Dies war nur eine kurze Einführung in Code First. Ein vollständiges Tutorial zu diesem Thema finden Sie unter Erstellen eines Entity Framework-Datenmodells für eine ASP.NET MVC-Anwendung . Als Nächstes sehen wir uns an, wie Sie den Modellklassen eine umfassendere Validierungslogik hinzufügen und einige Geschäftsregeln erzwingen können.