Udostępnij za pośrednictwem


Dodanie nowego pola

Autor: Rick Anderson

Uwaga

Zaktualizowana wersja tego samouczka jest dostępna tutaj przy użyciu najnowszej wersji programu Visual Studio. W nowym samouczku jest używany ASP.NET Core MVC, który oferuje wiele ulepszeń w tym samouczku.

W tym samouczku przedstawiono ASP.NET Core MVC z kontrolerami i widokami. Platforma Razor Pages to nowa alternatywa dla platformy ASP.NET Core— oparty na stronach model programowania, który ułatwia tworzenie internetowego interfejsu użytkownika i wydajniejsze. Zalecamy wypróbowanie samouczka razor Pages przed wersją MVC. Samouczek razor Pages:

  • Jest łatwiejsze do naśladowania.
  • Obejmuje więcej funkcji.
  • Jest preferowanym podejściem do tworzenia nowych aplikacji.

W tej sekcji użyjesz migracje Code First platformy Entity Framework, aby przeprowadzić migrację niektórych zmian do klas modelu, dzięki czemu zmiana zostanie zastosowana do bazy danych.

Domyślnie gdy używasz programu Entity Framework Code First do automatycznego tworzenia bazy danych, tak jak wcześniej w tym samouczku, funkcja Code First dodaje tabelę do bazy danych, aby ułatwić śledzenie, czy schemat bazy danych jest zsynchronizowany z klasami modelu, z których została wygenerowana. Jeśli nie są one zsynchronizowane, program Entity Framework zgłasza błąd. Ułatwia to śledzenie problemów w czasie programowania, które w przeciwnym razie można znaleźć tylko (przez niejasne błędy) w czasie wykonywania.

Konfigurowanie Migracje Code First zmian modelu

Przejdź do Eksplorator rozwiązań. Kliknij prawym przyciskiem myszy plik Movies.mdf i wybierz polecenie Usuń , aby usunąć bazę danych filmów. Jeśli nie widzisz pliku Movies.mdf , kliknij ikonę Pokaż wszystkie pliki pokazaną poniżej w czerwonym konspekcie.

Zrzut ekranu przedstawiający kartę Kontroler filmów dot c s i Eksplorator rozwiązań otworzyć. Ikona Pokaż wszystkie pliki jest zakreślina na czerwono.

Skompiluj aplikację, aby upewnić się, że nie ma żadnych błędów.

W menu Narzędzia kliknij pozycję Menedżer pakietów NuGet, a następnie kliknij pozycję Konsola menedżera pakietów.

Dodawanie dodatku Pack Man

W oknie Menedżer pakietów Console (Konsola Menedżer pakietów) po wyświetleniu monitu PM> wprowadź

Enable-Migrations -ContextTypeName MvcFilm.Models.MovieDBContext

Zrzut ekranu przedstawiający okno konsoli Menedżer pakietów. Tekst w poleceniu Włącz migracje jest wyróżniony.

Polecenie Enable-Migrations (pokazane powyżej) tworzy plik Configuration.cs w nowym folderze Migrations .

Zrzut ekranu przedstawiający Eksplorator rozwiązań. Wybrano podfolder Configuration dot c s folderu Migrations.

Program Visual Studio otwiera plik Configuration.cs . Zastąp metodę Seed w pliku Configuration.cs następującym kodem:

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

Zatrzymaj wskaźnik myszy na czerwonej linii zygzakowa w obszarze Movie , a następnie kliknij, a następnie kliknij polecenie Show Potential Fixes Przy użyciu mvcFilm.Models;

Zrzut ekranu przedstawiający menu Pokaż potencjalne poprawki. Przy użyciu modeli kropki filmów języka M V C jest zaznaczona i nie można odnaleźć alertu.

Spowoduje to dodanie następującej instrukcji using:

using MvcMovie.Models;

Uwaga

Migracje Code First wywołuje metodę Seed po każdej migracji (czyli wywoływaniu bazy danych update-database w konsoli Menedżer pakietów), a ta metoda aktualizuje wiersze, które zostały już wstawione lub wstawia je, jeśli jeszcze nie istnieją.

Metoda AddOrUpdate w poniższym kodzie wykonuje operację "upsert":

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
    }

Ponieważ metoda Seed jest uruchamiana z każdą migracją, nie można po prostu wstawić danych, ponieważ wiersze, które próbujesz dodać, będą już dostępne po pierwszej migracji, która tworzy bazę danych. Operacja "upsert" uniemożliwia błędy, które mogą wystąpić, jeśli spróbujesz wstawić wiersz, który już istnieje, ale zastępuje wszelkie zmiany danych, które mogły zostać wprowadzone podczas testowania aplikacji. W przypadku danych testowych w niektórych tabelach możesz nie chcieć tego zrobić: w niektórych przypadkach zmiana danych podczas testowania zmian ma pozostać po aktualizacjach bazy danych. W takim przypadku chcesz wykonać operację wstawiania warunkowego: wstaw wiersz tylko wtedy, gdy jeszcze nie istnieje.

Pierwszy parametr przekazany do metody AddOrUpdate określa właściwość do użycia, aby sprawdzić, czy wiersz już istnieje. W przypadku danych testowych filmów, które podajesz, właściwość może być używana do tego celu, Title ponieważ każdy tytuł na liście jest unikatowy:

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

W tym kodzie przyjęto założenie, że tytuły są unikatowe. Jeśli ręcznie dodasz zduplikowany tytuł, otrzymasz następujący wyjątek przy następnym wykonaniu migracji.

Sekwencja zawiera więcej niż jeden element

Aby uzyskać więcej informacji na temat metody AddOrUpdate, zobacz Take care with EF 4.3 AddOrUpdate Method.

Naciśnij CTRL-SHIFT-B, aby skompilować projekt.(Poniższe kroki nie powiedzą się, jeśli nie skompilujesz w tym momencie).

Następnym krokiem DbMigration jest utworzenie klasy na potrzeby migracji początkowej. Ta migracja tworzy nową bazę danych, dlatego plik movie.mdf został usunięty w poprzednim kroku.

W oknie Menedżer pakietów Console (Konsola Menedżer pakietów) wprowadź polecenie add-migration Initial , aby utworzyć migrację początkową. Nazwa "Initial" jest dowolna i służy do nazywania utworzonego pliku migracji.

Zrzut ekranu przedstawiający konsolę Menedżer pakietów. Tekst w poleceniu dodawania migracji jest wyróżniony.

Migracje Code First tworzy inny plik klasy w pliku Folder Migrations (o nazwie {DateStamp}_Initial.cs ), a ta klasa zawiera kod tworzący schemat bazy danych. Nazwa pliku migracji jest wstępnie naprawiona za pomocą znacznika czasu, aby ułatwić zamawianie. Zapoznaj się z plikiem {DateStamp}_Initial.cs zawierającym instrukcje tworzenia Movies tabeli dla bazy danych Movie DB. Po zaktualizowaniu bazy danych w poniższych instrukcjach ten plik _Initial.cs {DateStamp}zostanie uruchomiony i utworzy schemat bazy danych. Następnie zostanie uruchomiona metoda Seed, aby wypełnić bazę danych danymi testowymi.

W konsoli Menedżer pakietów wprowadź polecenie update-database , aby utworzyć bazę danych i uruchomić metodę Seed .

Zrzut ekranu przedstawiający konsolę Menedżer pakietów. Polecenie aktualizacji bazy danych znajduje się w oknie.

Jeśli wystąpi błąd wskazujący, że tabela już istnieje i nie można jej utworzyć, prawdopodobnie dlatego, że aplikacja została uruchomiona po usunięciu bazy danych i przed wykonaniem polecenia update-database. W takim przypadku ponownie usuń plik Movies.mdf i ponów próbę update-database polecenia. Jeśli nadal wystąpi błąd, usuń folder migracji i zawartość, a następnie zacznij od instrukcji w górnej części tej strony (czyli usuń plik Movies.mdf , a następnie przejdź do pozycji Włącz migracje). Jeśli nadal wystąpi błąd, otwórz program SQL Server Eksplorator obiektów i usuń bazę danych z listy. Jeśli zostanie wyświetlony komunikat o błędzie "Nie można dołączyć pliku .mdf jako bazy danych", usuń właściwość Katalogu początkowego w ramach parametry połączenia w pliku web.config.

Uruchom aplikację i przejdź do adresu URL /Movies . Zostaną wyświetlone dane inicjujne.

Zrzut ekranu przedstawiający indeks filmów M V C z czterema wymienionymi filmami.

Dodawanie właściwości ratingu do modelu filmowego

Zacznij od dodania nowej Rating właściwości do istniejącej Movie klasy. Otwórz plik Models\Movie.cs i dodaj właściwość podobną do następującejRating:

public string Rating { get; set; }

Kompletna Movie klasa wygląda teraz jak następujący kod:

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; }
}

Skompiluj aplikację (Ctrl+Shift+B).

Ponieważ dodano nowe pole do Movie klasy, należy również zaktualizować listę dozwolonych powiązań, aby ta nowa właściwość została uwzględniona. bind Zaktualizuj atrybut metod Create i Edit akcji, aby uwzględnić Rating właściwość :

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

Należy również zaktualizować szablony widoków, aby wyświetlać, tworzyć i edytować nową Rating właściwość w widoku przeglądarki.

Otwórz plik \Views\Movies\Index.cshtml i dodaj <th>Rating</th> nagłówek kolumny tuż po kolumnie Cena. Następnie dodaj kolumnę <td> pod koniec szablonu, aby renderować @item.Rating wartość. Poniżej przedstawiono wygląd zaktualizowanego szablonu widoku Index.cshtml :

@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>

Następnie otwórz plik \Views\Movies\Create.cshtml i dodaj Rating pole z wyróżnionym znacznikiem. Spowoduje to renderowanie pola tekstowego, aby można było określić ocenę podczas tworzenia nowego filmu.

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

Kod aplikacji został zaktualizowany w celu obsługi nowej Rating właściwości.

Uruchom aplikację i przejdź do adresu URL /Movies . W takim przypadku zobaczysz jednak jeden z następujących błędów:

Zrzut ekranu przedstawiający błąd Nieobsługiwany użytkownik wyjątku.

Model tworzący kopię zapasową kontekstu "MovieDBContext" zmienił się od czasu utworzenia bazy danych. Rozważ użycie Migracje Code First do zaktualizowania bazy danych (https://go.microsoft.com/fwlink/?LinkId=238269).

Zrzut ekranu przedstawiający przeglądarkę z powiadomieniem o błędzie serwera w aplikacji.

Ten błąd występuje, ponieważ zaktualizowana Movie klasa modelu w aplikacji różni się teraz od schematu Movie tabeli istniejącej bazy danych. (W tabeli bazy danych nie Rating ma żadnej kolumny).

Istnieje kilka podejść do rozwiązywania błędu:

  1. Program Entity Framework automatycznie upuść i ponownie utworzyć bazę danych na podstawie nowego schematu klasy modelu. Takie podejście jest bardzo wygodne na wczesnym etapie cyklu programowania podczas aktywnego programowania w testowej bazie danych; umożliwia szybkie rozwijanie modelu i schematu bazy danych. Wadą jest jednak utratę istniejących danych w bazie danych — więc nie chcesz używać tego podejścia w produkcyjnej bazie danych. Użycie inicjatora do automatycznego rozmieszczania bazy danych z danymi testowymi jest często produktywnym sposobem tworzenia aplikacji. Aby uzyskać więcej informacji na temat inicjatorów bazy danych programu Entity Framework, zobacz samouczek ASP.NET MVC/Entity Framework.
  2. Jawnie zmodyfikuj schemat istniejącej bazy danych, tak aby odpowiadał klasom modelu. Zaletą tego podejścia jest przechowywanie danych. Tę zmianę można wprowadzić ręcznie lub tworząc skrypt zmiany bazy danych.
  3. Użyj Migracje Code First, aby zaktualizować schemat bazy danych.

Na potrzeby tego samouczka użyjemy Migracje Code First.

Zaktualizuj metodę Seed, aby zapewnić jej wartość dla nowej kolumny. Otwórz plik Migrations\Configuration.cs i dodaj pole Ocena do każdego obiektu Movie.

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

Skompiluj rozwiązanie, a następnie otwórz okno konsoli Menedżer pakietów i wprowadź następujące polecenie:

add-migration Rating

Polecenie add-migration informuje platformę migracji, aby zbadać bieżący model filmu przy użyciu bieżącego schematu bazy danych filmu i utworzyć niezbędny kod do zmigrowania bazy danych do nowego modelu. Nazwa Ocena jest dowolna i służy do nazywania pliku migracji. Warto użyć znaczącej nazwy dla kroku migracji.

Po zakończeniu tego polecenia program Visual Studio otwiera plik klasy definiujący nową DbMigration klasę pochodną, a w Up metodzie można zobaczyć kod tworzący nową kolumnę.

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

Skompiluj rozwiązanie, a następnie wprowadź update-database polecenie w oknie Menedżer pakietów Konsola.

Na poniższej ilustracji przedstawiono dane wyjściowe w oknie konsoli Menedżer pakietów (ocena sygnatury daty będzie inna).

Zrzut ekranu przedstawiający okno konsoli Menedżer pakietów z wprowadzonym poleceniem aktualizacji bazy danych.

Uruchom ponownie aplikację i przejdź do adresu URL /Movies. Zostanie wyświetlone nowe pole Ocena.

Zrzut ekranu przedstawiający listę indeksów filmów języka M V C z dodanym polem Ocena.

Kliknij link Utwórz nowy, aby dodać nowy film. Pamiętaj, że możesz dodać ocenę.

7_CreateRioII

Kliknij pozycję Utwórz. Nowy film, w tym ocena, teraz pojawia się na liście filmów:

7_ourNewMovie_SM

Teraz, gdy projekt korzysta z migracji, nie trzeba usuwać bazy danych podczas dodawania nowego pola lub aktualizowania schematu. W następnej sekcji wprowadzimy więcej zmian schematu i użyjemy migracji w celu zaktualizowania bazy danych.

Należy również dodać Rating pole do szablonów widoku Edytuj, Szczegóły i Usuń.

Możesz ponownie wprowadzić polecenie "update-database" w oknie konsoli Menedżer pakietów i nie zostanie uruchomiony żaden kod migracji, ponieważ schemat jest zgodny z modelem. Jednak uruchomienie polecenia "update-database" spowoduje ponowne uruchomienie Seed metody, a jeśli zmienisz dowolne dane inicjujące, zmiany zostaną utracone, ponieważ Seed metoda upserts danych. Więcej informacji na temat metody można przeczytać w ASP.NET popularnym samouczku Seedplatformy MVC/Entity Framework w usłudze Tom Dykstra.

W tej sekcji przedstawiono sposób modyfikowania obiektów modelu i synchronizowania bazy danych ze zmianami. Przedstawiono również sposób wypełniania nowo utworzonej bazy danych przykładowymi danymi, dzięki czemu można wypróbować scenariusze. To było tylko krótkie wprowadzenie do kodu First, zobacz Creating an Entity Framework Data Model for an ASP.NET MVC Application (Tworzenie modelu danych platformy Entity Framework dla ASP.NET aplikacji MVC), aby uzyskać bardziej kompletny samouczek na ten temat. Następnie przyjrzyjmy się temu, jak można dodać bogatszą logikę walidacji do klas modeli i umożliwić wymuszanie niektórych reguł biznesowych.