"
ASP.NET (snapshot 2017) Microsoft documentation and samples

Adding a New Field

By Rick Anderson

In this section you’ll use Entity Framework Code First Migrations to add a new field to the model and migrate that change to the database.

When you use EF Code First to automatically create a database, Code First adds a table to the database to help track whether the schema of the database is in sync with the model classes it was generated from. If they aren’t in sync, EF throws an exception. This makes it easier to find inconsistent database/code issues.

Adding a Rating Property to the Movie Model

Open the Models/Movie.cs file and add a Rating property:

[!code-csharpMain]

   1:  //#define MovieDateRating
   2:  #if MovieDateRating
   3:  using System;
   4:  using System.ComponentModel.DataAnnotations;
   5:  namespace MvcMovie.Models
   6:  {
   7:      public class Movie
   8:      {
   9:          public int ID { get; set; }
  10:          public string Title { get; set; }
  11:   
  12:          [Display(Name = "Release Date")]
  13:          [DataType(DataType.Date)]
  14:          public DateTime ReleaseDate { get; set; }
  15:          public string Genre { get; set; }
  16:          public decimal Price { get; set; }
  17:          public string Rating { get; set; }
  18:      }
  19:   
  20:  }
  21:  #endif

Build the app (Ctrl+Shift+B).

Because you’ve added a new field to the Movie class, you also need to update the binding white list so this new property will be included. In MoviesController.cs, update the [Bind] attribute for both the Create and Edit action methods to include the Rating property:

You also need to update the view templates in order to display, create and edit the new Rating property in the browser view.

Edit the /Views/Movies/Index.cshtml file and add a Rating field:

[!code-HTMLMain]

   1:  @model MvcMovie.Models.MovieGenreViewModel
   2:   
   3:  @{
   4:      ViewData["Title"] = "Index";
   5:  }
   6:   
   7:  <h2>Index</h2>
   8:   
   9:  <p>
  10:      <a asp-action="Create">Create New</a>
  11:  </p>
  12:   
  13:  <form asp-controller="Movies" asp-action="Index" method="get">
  14:      <p>
  15:          <select asp-for="movieGenre" asp-items="Model.genres">
  16:              <option value="">All</option>
  17:          </select>
  18:   
  19:          Title: <input type="text" name="SearchString">
  20:          <input type="submit" value="Filter" />
  21:      </p>
  22:  </form>
  23:   
  24:  <table class="table">
  25:      <thead>
  26:          <tr>
  27:              <th>
  28:                  @Html.DisplayNameFor(model => model.movies[0].Title)
  29:              </th>
  30:              <th>
  31:                  @Html.DisplayNameFor(model => model.movies[0].ReleaseDate)
  32:              </th>
  33:              <th>
  34:                  @Html.DisplayNameFor(model => model.movies[0].Genre)
  35:              </th>
  36:              <th>
  37:                  @Html.DisplayNameFor(model => model.movies[0].Price)
  38:              </th>
  39:              <th>
  40:                  @Html.DisplayNameFor(model => model.movies[0].Rating)
  41:              </th>
  42:              <th></th>
  43:          </tr>
  44:      </thead>
  45:      <tbody>
  46:          @foreach (var item in Model.movies)
  47:          {
  48:              <tr>
  49:                  <td>
  50:                      @Html.DisplayFor(modelItem => item.Title)
  51:                  </td>
  52:                  <td>
  53:                      @Html.DisplayFor(modelItem => item.ReleaseDate)
  54:                  </td>
  55:                  <td>
  56:                      @Html.DisplayFor(modelItem => item.Genre)
  57:                  </td>
  58:                  <td>
  59:                      @Html.DisplayFor(modelItem => item.Price)
  60:                  </td>
  61:                  <td>
  62:                      @Html.DisplayFor(modelItem => item.Rating)
  63:                  </td>
  64:                  <td>
  65:                      <a asp-action="Edit" asp-route-id="@item.ID">Edit</a> |
  66:                      <a asp-action="Details" asp-route-id="@item.ID">Details</a> |
  67:                      <a asp-action="Delete" asp-route-id="@item.ID">Delete</a>
  68:                  </td>
  69:              </tr>
  70:          }
  71:      </tbody>
  72:  </table>

Update the /Views/Movies/Create.cshtml with a Rating field. You can copy/paste the previous “form group” and let intelliSense help you update the fields. IntelliSense works with (xref:)Tag Helpers. Note: In the RTM verison of Visual Studio 2017 you need to install the Razor Language Services for Razor intelliSense. This will be fixed in the next release.

The developer has typed the letter R for the attribute value of asp-for in the second label element of the view. An Intellisense contextual menu has appeared showing the available fields, including Rating, which is highlighted in the list automatically. When the developer clicks the field or presses Enter on the keyboard, the value will be set to Rating.
The developer has typed the letter R for the attribute value of asp-for in the second label element of the view. An Intellisense contextual menu has appeared showing the available fields, including Rating, which is highlighted in the list automatically. When the developer clicks the field or presses Enter on the keyboard, the value will be set to Rating.

The app won’t work until we update the DB to include the new field. If you run it now, you’ll get the following SqlException:

SqlException: Invalid column name 'Rating'.

You’re seeing this error because the updated Movie model class is different than the schema of the Movie table of the existing database. (There’s no Rating column in the database table.)

There are a few approaches to resolving the error:

  1. Have the Entity Framework automatically drop and re-create the database based on the new model class schema. This approach is very convenient early in the development cycle when you are doing active development on a test database; it allows you to quickly evolve the model and database schema together. The downside, though, is that you lose existing data in the database — so you don’t want to use this approach on a production database! Using an initializer to automatically seed a database with test data is often a productive way to develop an application.

  2. Explicitly modify the schema of the existing database so that it matches the model classes. The advantage of this approach is that you keep your data. You can make this change either manually or by creating a database change script.

  3. Use Code First Migrations to update the database schema.

For this tutorial, we’ll use Code First Migrations.

Update the SeedData class so that it provides a value for the new column. A sample change is shown below, but you’ll want to make this change for each new Movie.

[!code-csharpMain]

   1:  #define SeedRating 
   2:  #if SeedRating
   3:   
   4:  using Microsoft.EntityFrameworkCore;
   5:  using Microsoft.Extensions.DependencyInjection;
   6:  using System;
   7:  using System.Linq;
   8:   
   9:  namespace MvcMovie.Models
  10:  {
  11:      public static class SeedData
  12:      {
  13:          public static void Initialize(IServiceProvider serviceProvider)
  14:          {
  15:              using (var context = new MvcMovieContext(
  16:                  serviceProvider.GetRequiredService<DbContextOptions<MvcMovieContext>>()))
  17:              {
  18:                  if (context.Movie.Any())
  19:                  {
  20:                      return;   // DB has been seeded
  21:                  }
  22:   
  23:                  context.Movie.AddRange(
  24:                  #region snippet1
  25:                       new Movie
  26:                       {
  27:                           Title = "When Harry Met Sally",
  28:                           ReleaseDate = DateTime.Parse("1989-1-11"),
  29:                           Genre = "Romantic Comedy",
  30:                           Rating = "R",
  31:                           Price = 7.99M
  32:                       },
  33:                  #endregion
  34:                       new Movie
  35:                       {
  36:                           Title = "Ghostbusters ",
  37:                           ReleaseDate = DateTime.Parse("1984-3-13"),
  38:                           Genre = "Comedy",
  39:                           Rating = "G",
  40:                           Price = 8.99M
  41:                       },
  42:   
  43:                       new Movie
  44:                       {
  45:                           Title = "Ghostbusters 2",
  46:                           ReleaseDate = DateTime.Parse("1986-2-23"),
  47:                           Genre = "Comedy",
  48:                           Rating = "PG",
  49:                           Price = 9.99M
  50:                       },
  51:   
  52:                     new Movie
  53:                     {
  54:                         Title = "Rio Bravo",
  55:                         ReleaseDate = DateTime.Parse("1959-4-15"),
  56:                         Genre = "Western",
  57:                         Rating = "NA",
  58:                         Price = 3.99M
  59:                     }
  60:                  );
  61:                  context.SaveChanges();
  62:              }
  63:          }
  64:      }
  65:  }
  66:   
  67:   
  68:   
  69:  #endif

Build the solution.

From the Tools menu, select NuGet Package Manager > Package Manager Console.

PMC menu
PMC menu

In the PMC, enter the following commands:

The Add-Migration command tells the migration framework to examine the current Movie model with the current Movie DB schema and create the necessary code to migrate the DB to the new model. The name “Rating” is arbitrary and is used to name the migration file. It’s helpful to use a meaningful name for the migration file.

If you delete all the records in the DB, the initialize will seed the DB and include the Rating field. You can do this with the delete links in the browser or from SSOX.

Run the app and verify you can create/edit/display movies with a Rating field. You should also add the Rating field to the Edit, Details, and Delete view templates.

Previous Next



Comments ( )
Link to this page: //www.vb-net.com/AspNet-DocAndSamples-2017/aspnetcore/tutorials/first-mvc-app/new-field.htm
< THANKS ME>