Code First new attribute

In this section, Entity Framework Code First migration is used to:

  • Add a new field to the model.
  • Migrate new fields to the database.

When you use EF Code First to automatically create a database, Code First will:

  • Add tables to the database to track the schema of the database.
  • Verify that the database is synchronized with the model class that generated it. If they are out of sync, EF throws an exception. This makes it easier to find inconsistent database / code problems.

Add rating properties to the movie model

Add the {Rating} attribute to models / movie cs:

C # replication
 
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int Id { get; set; }
        public string? Title { get; set; }

        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string? Genre { get; set; }

        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }
        public string? Rating {  get; set; }
    }
}

Generate application

Ctrl+Shift+B

Because a new field has been added to the Movie class, you need to update the property binding list to include this new property. In moviescontroller CS, update the [Bind] attribute of the 'Create' and 'Edit' operation methods to include the 'Rating' attribute:

C # replication
 
[Bind("Id,Title,ReleaseDate,Genre,Price,Rating")]

Update the view template to display, create, and edit new Rating properties in the browser view.

Edit / views / movies / index Cshtml file and add the {Rating} field:

CSHTML copy
 
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].Title)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].ReleaseDate)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].Genre)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].Price)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Movies[0].Rating)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model.Movies)
        {
            <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>
                    <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
                    <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
                    <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
                </td>
            </tr>
        }
    </tbody>
</table>

Update / views / movies / create. With the # Rating # field cshtml.

You can copy / paste the previous form group and have IntelliSense help update the fields. IntelliSense for Tag helper.

Update the remaining templates.

Update the {SeedData} class to provide the value of the new column. The sample changes are shown below, but you may need to make this change for each new Movie.

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

The application will not work properly until the DB is updated to include new fields. If it runs now, the following SqlException will be thrown:

SqlException: Invalid column name 'Rating'.

This error occurs because the updated Movie model class is different from the Movie table schema of the existing database. (there is no {Rating} column in the database table.)

There are several ways to resolve this error:

  1. Let the Entity Framework automatically discard and recreate the database based on the new model class schema. When developing on the test database, this method is very convenient in the early development cycle; Through it, we can quickly improve the model and database architecture together. However, the disadvantage is that the existing data in the database will be lost - so do not use this method on the production database! Using initializers to automatically seed the database with test data is often an effective way to develop applications. This is a good approach for early development and use of SQLite.

  2. Explicitly modify the existing database schema to match the model class. The advantage of this method is that the data can be retained. You can make this change manually or by creating a database change script.

  3. Update the database schema using Code First migration.

For this tutorial, use Code First migration.

From the tools menu, select NuGet package manager > package manager console.

In PMC, enter the following command:

PowerShell replication
 
Add-Migration Rating
Update-Database

The add migration command will inform the migration framework to check the current Movie DB model using 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 is helpful to use meaningful names for migrated files.

If all records in the DB are deleted, the initialization method will seed the DB and include the {Rating} field.

Run the application and verify that you can create, edit, and display movies with a Rating field.

Keywords: .NET

Added by Mardoxx on Wed, 12 Jan 2022 02:54:25 +0200