Parte 7, adicionar um novo campo a um Razor Pages no ASP.NET Core

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

De Rick Anderson

Nesta seção, as Migrações do Entity Framework Code First são usadas para:

  • Adicionar um novo campo ao modelo.
  • Migrar a nova alteração de esquema de campo para o banco de dados.

Ao usar o Code First do EF para criar automaticamente um banco de dados, o Code First:

  • Adiciona uma tabela __EFMigrationsHistory ao banco de dados para acompanhar se o esquema do banco de dados está sincronizado com as classes de modelo das quais ele foi gerado.
  • Gera uma exceção se as classes de modelo não estiverem sincronizadas com o banco de dados.

A verificação automática de que o esquema e o modelo estão sincronizados facilita a localização de problemas de código de banco de dados inconsistentes.

Adicionando uma propriedade de classificação ao modelo de filme

  1. Abra o arquivo Models/Movie.cs e adicione uma propriedade Rating:

    public class Movie
    {
        public int Id { get; set; }
        public string Title { get; set; } = string.Empty;
    
        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; } = string.Empty;
    
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }
        public string Rating { get; set; } = string.Empty;
    }
    
  2. Edite Pages/Movies/Index.cshtmle adicione um campo Rating:

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <p>
        <a asp-page="Create">Create New</a>
    </p>
    
    <form>
        <p>
            <select asp-for="MovieGenre" asp-items="Model.Genres">
                <option value="">All</option>
            </select>
            Title: <input type="text" asp-for="SearchString" />
            <input type="submit" value="Filter" />
        </p>
    </form>
    
    <table class="table">
    
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Title)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Genre)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Price)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Rating)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model.Movie)
            {
                <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-page="./Edit" asp-route-id="@item.Id">Edit</a> |
                        <a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
                        <a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    
  3. Atualize as seguintes páginas com um campo Rating:

O aplicativo não funcionará até que o banco de dados seja atualizado para incluir o novo campo. A execução do aplicativo sem uma atualização no banco de dados gera uma SqlException:

SqlException: Invalid column name 'Rating'.

A exceção SqlException é causada por a classe de modelo Movie atualizada ser diferente do esquema da tabela Movie do banco de dados. Não há nenhuma coluna Rating na tabela de banco de dados.

Existem algumas abordagens para resolver o erro:

  1. Faça com que o Entity Framework remova automaticamente e recrie o banco de dados usando o novo esquema de classe de modelo. Essa abordagem é conveniente no início do ciclo de desenvolvimento, pois ela permite que você desenvolva rapidamente o modelo e o esquema de banco de dados juntos. A desvantagem é que você perde os dados existentes no banco de dados. Não use essa abordagem em um banco de dados de produção. A remoção do banco de dados em alterações de esquema e o uso de um inicializador para propagar automaticamente o banco de dados com os dados de teste é muitas vezes uma maneira produtiva de desenvolver um aplicativo.
  2. Modifique explicitamente o esquema do banco de dados existente para que ele corresponda às classes de modelo. A vantagem dessa abordagem é manter os dados. Faça essa alteração manualmente ou criando um script de alteração de banco de dados.
  3. Use as Migrações do Code First para atualizar o esquema de banco de dados.

Para este tutorial, use as Migrações do Code First.

Atualize a classe SeedData para que ela forneça um valor para a nova coluna. Uma alteração de amostra é mostrada abaixo, mas faça essa alteração em cada bloco new Movie.

context.Movie.AddRange(
    new Movie
    {
        Title = "When Harry Met Sally",
        ReleaseDate = DateTime.Parse("1989-2-12"),
        Genre = "Romantic Comedy",
        Price = 7.99M,
        Rating = "R"
    },

Consulte o arquivo SeedData.cs concluído.

Criar o aplicativo

Pressione CTRL+SHIFT+B

Adicionar uma migração para o campo de classificação

  1. No menu Ferramentas, selecione Gerenciador de Pacotes NuGet > Console do Gerenciador de Pacotes.

  2. No PMC, insira os seguintes comandos:

    Add-Migration Rating
    Update-Database
    

O comando Add-Migration informa à estrutura:

  • Compare o modelo de Movie com o esquema de banco de dados Movie.
  • Crie código para migrar o esquema de banco de dados para o novo modelo.

O nome “Classificação” é arbitrário e é usado para nomear o arquivo de migração. É útil usar um nome significativo para o arquivo de migração.

O comando Update-Database informa à estrutura para aplicar as alterações de esquema ao banco de dados e preservar os dados existentes.

Excluir todos os registros no banco de dados fará com que o inicializador propague o banco de dados e inclua o campo Rating. A exclusão pode ser feita com os links de exclusão no navegador ou no SSOX (Pesquisador de Objetos do SQL Server).

Outra opção é excluir o banco de dados e usar as migrações para recriar o banco de dados. Para excluir o banco de dados no SSOX:

  1. Selecione o banco de dados no SSOX.

  2. Clique com o botão direito do mouse no banco de dados e selecione Excluir.

  3. Marque Fechar conexões existentes.

  4. Selecione OK.

  5. No PMC, atualize o banco de dados:

    Update-Database
    

Execute o aplicativo e verifique se você pode criar, editar e exibir filmes com um campo Rating. Se o banco de dados não for propagado, defina um ponto de interrupção no método SeedData.Initialize.

Próximas etapas

Nesta seção, as Migrações do Entity Framework Code First são usadas para:

  • Adicionar um novo campo ao modelo.
  • Migrar a nova alteração de esquema de campo para o banco de dados.

Ao usar o Code First do EF para criar automaticamente um banco de dados, o Code First:

  • Adiciona uma tabela __EFMigrationsHistory ao banco de dados para acompanhar se o esquema do banco de dados está sincronizado com as classes de modelo das quais ele foi gerado.
  • Gera uma exceção se as classes de modelo não estiverem sincronizadas com o banco de dados.

A verificação automática de que o esquema e o modelo estão sincronizados facilita a localização de problemas de código de banco de dados inconsistentes.

Adicionando uma propriedade de classificação ao modelo de filme

  1. Abra o arquivo Models/Movie.cs e adicione uma propriedade Rating:

    public class Movie
    {
        public int Id { get; set; }
        public string Title { get; set; } = string.Empty;
    
        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; } = string.Empty;
    
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }
        public string Rating { get; set; } = string.Empty;
    }
    
  2. Edite Pages/Movies/Index.cshtmle adicione um campo Rating:

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <p>
        <a asp-page="Create">Create New</a>
    </p>
    
    <form>
        <p>
            <select asp-for="MovieGenre" asp-items="Model.Genres">
                <option value="">All</option>
            </select>
            Title: <input type="text" asp-for="SearchString" />
            <input type="submit" value="Filter" />
        </p>
    </form>
    
    <table class="table">
    
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Title)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Genre)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Price)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Rating)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model.Movie)
            {
                <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-page="./Edit" asp-route-id="@item.Id">Edit</a> |
                        <a asp-page="./Details" asp-route-id="@item.Id">Details</a> |
                        <a asp-page="./Delete" asp-route-id="@item.Id">Delete</a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    
  3. Atualize as seguintes páginas com um campo Rating:

O aplicativo não funcionará até que o banco de dados seja atualizado para incluir o novo campo. A execução do aplicativo sem uma atualização no banco de dados gera uma SqlException:

SqlException: Invalid column name 'Rating'.

A exceção SqlException é causada por a classe de modelo Movie atualizada ser diferente do esquema da tabela Movie do banco de dados. Não há nenhuma coluna Rating na tabela de banco de dados.

Existem algumas abordagens para resolver o erro:

  1. Faça com que o Entity Framework remova automaticamente e recrie o banco de dados usando o novo esquema de classe de modelo. Essa abordagem é conveniente no início do ciclo de desenvolvimento, pois ela permite que você desenvolva rapidamente o modelo e o esquema de banco de dados juntos. A desvantagem é que você perde os dados existentes no banco de dados. Não use essa abordagem em um banco de dados de produção. A remoção do banco de dados em alterações de esquema e o uso de um inicializador para propagar automaticamente o banco de dados com os dados de teste é muitas vezes uma maneira produtiva de desenvolver um aplicativo.
  2. Modifique explicitamente o esquema do banco de dados existente para que ele corresponda às classes de modelo. A vantagem dessa abordagem é manter os dados. Faça essa alteração manualmente ou criando um script de alteração de banco de dados.
  3. Use as Migrações do Code First para atualizar o esquema de banco de dados.

Para este tutorial, use as Migrações do Code First.

Atualize a classe SeedData para que ela forneça um valor para a nova coluna. Uma alteração de amostra é mostrada abaixo, mas faça essa alteração em cada bloco new Movie.

context.Movie.AddRange(
    new Movie
    {
        Title = "When Harry Met Sally",
        ReleaseDate = DateTime.Parse("1989-2-12"),
        Genre = "Romantic Comedy",
        Price = 7.99M,
        Rating = "R"
    },

Consulte o arquivo SeedData.cs concluído.

Criar o aplicativo

Pressione CTRL+SHIFT+B

Adicionar uma migração para o campo de classificação

  1. No menu Ferramentas, selecione Gerenciador de Pacotes NuGet > Console do Gerenciador de Pacotes.

  2. No PMC, insira os seguintes comandos:

    Add-Migration Rating
    Update-Database
    

O comando Add-Migration informa à estrutura:

  • Compare o modelo de Movie com o esquema de banco de dados Movie.
  • Crie código para migrar o esquema de banco de dados para o novo modelo.

O nome “Classificação” é arbitrário e é usado para nomear o arquivo de migração. É útil usar um nome significativo para o arquivo de migração.

O comando Update-Database informa à estrutura para aplicar as alterações de esquema ao banco de dados e preservar os dados existentes.

Excluir todos os registros no banco de dados fará com que o inicializador propague o banco de dados e inclua o campo Rating. A exclusão pode ser feita com os links de exclusão no navegador ou no SSOX (Pesquisador de Objetos do SQL Server).

Outra opção é excluir o banco de dados e usar as migrações para recriar o banco de dados. Para excluir o banco de dados no SSOX:

  1. Selecione o banco de dados no SSOX.

  2. Clique com o botão direito do mouse no banco de dados e selecione Excluir.

  3. Marque Fechar conexões existentes.

  4. Selecione OK.

  5. No PMC, atualize o banco de dados:

    Update-Database
    

Execute o aplicativo e verifique se você pode criar, editar e exibir filmes com um campo Rating. Se o banco de dados não for propagado, defina um ponto de interrupção no método SeedData.Initialize.

Próximas etapas

Nesta seção, as Migrações do Entity Framework Code First são usadas para:

  • Adicionar um novo campo ao modelo.
  • Migrar a nova alteração de esquema de campo para o banco de dados.

Ao usar o Code First do EF para criar automaticamente um banco de dados, o Code First:

  • Adiciona uma tabela __EFMigrationsHistory ao banco de dados para acompanhar se o esquema do banco de dados está sincronizado com as classes de modelo das quais ele foi gerado.
  • Gera uma exceção se as classes de modelo não estiverem sincronizadas com o banco de dados.

A verificação automática de que o esquema e o modelo estão sincronizados facilita a localização de problemas de código de banco de dados inconsistentes.

Adicionando uma propriedade de classificação ao modelo de filme

  1. Abra o arquivo Models/Movie.cs e adicione uma propriedade Rating:

    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; } = string.Empty;
    
        [Display(Name = "Release Date")]
        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; } = string.Empty;
    
        [Column(TypeName = "decimal(18, 2)")]
        public decimal Price { get; set; }
        public string Rating { get; set; } = string.Empty;
    }
    
  2. Edite Pages/Movies/Index.cshtmle adicione um campo Rating:

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <p>
        <a asp-page="Create">Create New</a>
    </p>
    
    <form>
        <p>
            <select asp-for="MovieGenre" asp-items="Model.Genres">
                <option value="">All</option>
            </select>
            Title: <input type="text" asp-for="SearchString" />
            <input type="submit" value="Filter" />
        </p>
    </form>
    
    <table class="table">
    
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Title)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Genre)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Price)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Rating)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model.Movie)
            {
                <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-page="./Edit" asp-route-id="@item.ID">Edit</a> |
                        <a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
                        <a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    
  3. Atualize as seguintes páginas com um campo Rating:

O aplicativo não funcionará até que o banco de dados seja atualizado para incluir o novo campo. A execução do aplicativo sem uma atualização no banco de dados gera uma SqlException:

SqlException: Invalid column name 'Rating'.

A exceção SqlException é causada por a classe de modelo Movie atualizada ser diferente do esquema da tabela Movie do banco de dados. Não há nenhuma coluna Rating na tabela de banco de dados.

Existem algumas abordagens para resolver o erro:

  1. Faça com que o Entity Framework remova automaticamente e recrie o banco de dados usando o novo esquema de classe de modelo. Essa abordagem é conveniente no início do ciclo de desenvolvimento, pois ela permite que você desenvolva rapidamente o modelo e o esquema de banco de dados juntos. A desvantagem é que você perde os dados existentes no banco de dados. Não use essa abordagem em um banco de dados de produção. A remoção do banco de dados em alterações de esquema e o uso de um inicializador para propagar automaticamente o banco de dados com os dados de teste é muitas vezes uma maneira produtiva de desenvolver um aplicativo.
  2. Modifique explicitamente o esquema do banco de dados existente para que ele corresponda às classes de modelo. A vantagem dessa abordagem é manter os dados. Faça essa alteração manualmente ou criando um script de alteração de banco de dados.
  3. Use as Migrações do Code First para atualizar o esquema de banco de dados.

Para este tutorial, use as Migrações do Code First.

Atualize a classe SeedData para que ela forneça um valor para a nova coluna. Uma alteração de amostra é mostrada abaixo, mas faça essa alteração em cada bloco new Movie.

context.Movie.AddRange(
    new Movie
    {
        Title = "When Harry Met Sally",
        ReleaseDate = DateTime.Parse("1989-2-12"),
        Genre = "Romantic Comedy",
        Price = 7.99M,
        Rating = "R"
    },

Consulte o arquivo SeedData.cs concluído.

Compile a solução.

Adicionar uma migração para o campo de classificação

  1. No menu Ferramentas, selecione Gerenciador de Pacotes NuGet > Console do Gerenciador de Pacotes.

  2. No PMC, insira os seguintes comandos:

    Add-Migration Rating
    Update-Database
    

O comando Add-Migration informa à estrutura:

  • Compare o modelo de Movie com o esquema de banco de dados Movie.
  • Crie código para migrar o esquema de banco de dados para o novo modelo.

O nome “Classificação” é arbitrário e é usado para nomear o arquivo de migração. É útil usar um nome significativo para o arquivo de migração.

O comando Update-Database informa à estrutura para aplicar as alterações de esquema ao banco de dados e preservar os dados existentes.

Excluir todos os registros no banco de dados fará com que o inicializador propague o banco de dados e inclua o campo Rating. A exclusão pode ser feita com os links de exclusão no navegador ou no SSOX (Pesquisador de Objetos do SQL Server).

Outra opção é excluir o banco de dados e usar as migrações para recriar o banco de dados. Para excluir o banco de dados no SSOX:

  1. Selecione o banco de dados no SSOX.

  2. Clique com o botão direito do mouse no banco de dados e selecione Excluir.

  3. Marque Fechar conexões existentes.

  4. Selecione OK.

  5. No PMC, atualize o banco de dados:

    Update-Database
    

Execute o aplicativo e verifique se você pode criar, editar e exibir filmes com um campo Rating. Se o banco de dados não for propagado, defina um ponto de interrupção no método SeedData.Initialize.

Próximas etapas

Exibir ou baixar um código de exemplo (como baixar).

Nesta seção, as Migrações do Entity Framework Code First são usadas para:

  • Adicionar um novo campo ao modelo.
  • Migrar a nova alteração de esquema de campo para o banco de dados.

Ao usar o Code First do EF para criar automaticamente um banco de dados, o Code First:

  • Adiciona uma tabela __EFMigrationsHistory ao banco de dados para acompanhar se o esquema do banco de dados está sincronizado com as classes de modelo das quais ele foi gerado.
  • Gera uma exceção se as classes de modelo não estiverem sincronizadas com o banco de dados.

A verificação automática de que o esquema e o modelo estão sincronizados facilita a localização de problemas de código de banco de dados inconsistentes.

Adicionando uma propriedade de classificação ao modelo de filme

  1. Abra o arquivo Models/Movie.cs e adicione uma propriedade Rating:

    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; }
    }
    
  2. Crie o aplicativo.

  3. Edite Pages/Movies/Index.cshtml e adicione um campo Rating:

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <p>
        <a asp-page="Create">Create New</a>
    </p>
    
    <form>
        <p>
            <select asp-for="MovieGenre" asp-items="Model.Genres">
                <option value="">All</option>
            </select>
            Title: <input type="text" asp-for="SearchString" />
            <input type="submit" value="Filter" />
        </p>
    </form>
    
    <table class="table">
    
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Title)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Genre)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Price)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Rating)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model.Movie)
            {
                <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-page="./Edit" asp-route-id="@item.ID">Edit</a> |
                        <a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
                        <a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    
  4. Atualize as seguintes páginas com um campo Rating:

O aplicativo não funcionará até que o banco de dados seja atualizado para incluir o novo campo. A execução do aplicativo sem uma atualização no banco de dados gera uma SqlException:

SqlException: Invalid column name 'Rating'.

A exceção SqlException é causada por a classe de modelo Movie atualizada ser diferente do esquema da tabela Movie do banco de dados. Não há nenhuma coluna Rating na tabela de banco de dados.

Existem algumas abordagens para resolver o erro:

  1. Faça com que o Entity Framework remova automaticamente e recrie o banco de dados usando o novo esquema de classe de modelo. Essa abordagem é conveniente no início do ciclo de desenvolvimento, pois ela permite que você desenvolva rapidamente o modelo e o esquema de banco de dados juntos. A desvantagem é que você perde os dados existentes no banco de dados. Não use essa abordagem em um banco de dados de produção. A remoção do banco de dados em alterações de esquema e o uso de um inicializador para propagar automaticamente o banco de dados com os dados de teste é muitas vezes uma maneira produtiva de desenvolver um aplicativo.

  2. Modifique explicitamente o esquema do banco de dados existente para que ele corresponda às classes de modelo. A vantagem dessa abordagem é manter os dados. Faça essa alteração manualmente ou criando um script de alteração de banco de dados.

  3. Use as Migrações do Code First para atualizar o esquema de banco de dados.

Para este tutorial, use as Migrações do Code First.

Atualize a classe SeedData para que ela forneça um valor para a nova coluna. Uma alteração de amostra é mostrada abaixo, mas faça essa alteração em cada bloco new Movie.

context.Movie.AddRange(
    new Movie
    {
        Title = "When Harry Met Sally",
        ReleaseDate = DateTime.Parse("1989-2-12"),
        Genre = "Romantic Comedy",
        Price = 7.99M,
        Rating = "R"
    },

Consulte o arquivo SeedData.cs concluído.

Compile a solução.

Adicionar uma migração para o campo de classificação

  1. No menu Ferramentas, selecione Gerenciador de Pacotes NuGet > Console do Gerenciador de Pacotes.

  2. No PMC, insira os seguintes comandos:

    Add-Migration Rating
    Update-Database
    

O comando Add-Migration informa à estrutura:

  • Compare o modelo de Movie com o esquema de banco de dados Movie.
  • Crie código para migrar o esquema de banco de dados para o novo modelo.

O nome “Classificação” é arbitrário e é usado para nomear o arquivo de migração. É útil usar um nome significativo para o arquivo de migração.

O comando Update-Database informa à estrutura para aplicar as alterações de esquema ao banco de dados e preservar os dados existentes.

Excluir todos os registros no banco de dados fará com que o inicializador propague o banco de dados e inclua o campo Rating. A exclusão pode ser feita com os links de exclusão no navegador ou no SSOX (Pesquisador de Objetos do SQL Server).

Outra opção é excluir o banco de dados e usar as migrações para recriar o banco de dados. Para excluir o banco de dados no SSOX:

  1. Selecione o banco de dados no SSOX.

  2. Clique com o botão direito do mouse no banco de dados e selecione Excluir.

  3. Marque Fechar conexões existentes.

  4. Selecione OK.

  5. No PMC, atualize o banco de dados:

    Update-Database
    

Execute o aplicativo e verifique se você pode criar/editar/exibir filmes com um campo Rating. Se o banco de dados não for propagado, defina um ponto de interrupção no método SeedData.Initialize.

Próximas etapas

Exibir ou baixar um código de exemplo (como baixar).

Nesta seção, as Migrações do Entity Framework Code First são usadas para:

  • Adicionar um novo campo ao modelo.
  • Migrar a nova alteração de esquema de campo para o banco de dados.

Ao usar o Code First do EF para criar automaticamente um banco de dados, o Code First:

  • Adiciona uma tabela __EFMigrationsHistory ao banco de dados para acompanhar se o esquema do banco de dados está sincronizado com as classes de modelo das quais ele foi gerado.
  • Gera uma exceção se as classes de modelo não estiverem sincronizadas com o banco de dados.

A verificação automática de que o esquema e o modelo estão sincronizados facilita a localização de problemas de código de banco de dados inconsistentes.

Adicionando uma propriedade de classificação ao modelo de filme

  1. Abra o arquivo Models/Movie.cs e adicione uma propriedade Rating:

    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; }
    }
    
  2. Crie o aplicativo.

  3. Edite Pages/Movies/Index.cshtml e adicione um campo Rating:

    @page
    @model RazorPagesMovie.Pages.Movies.IndexModel
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <p>
        <a asp-page="Create">Create New</a>
    </p>
    
    <form>
        <p>
            <select asp-for="MovieGenre" asp-items="Model.Genres">
                <option value="">All</option>
            </select>
            Title: <input type="text" asp-for="SearchString" />
            <input type="submit" value="Filter" />
        </p>
    </form>
    
    <table class="table">
    
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Title)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].ReleaseDate)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Genre)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Price)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Movie[0].Rating)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            @foreach (var item in Model.Movie)
            {
                <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-page="./Edit" asp-route-id="@item.ID">Edit</a> |
                        <a asp-page="./Details" asp-route-id="@item.ID">Details</a> |
                        <a asp-page="./Delete" asp-route-id="@item.ID">Delete</a>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    
  4. Atualize as seguintes páginas com um campo Rating:

O aplicativo não funcionará até que o banco de dados seja atualizado para incluir o novo campo. A execução do aplicativo sem uma atualização no banco de dados gera uma SqlException:

SqlException: Invalid column name 'Rating'.

A exceção SqlException é causada por a classe de modelo Movie atualizada ser diferente do esquema da tabela Movie do banco de dados. Não há nenhuma coluna Rating na tabela de banco de dados.

Existem algumas abordagens para resolver o erro:

  1. Faça com que o Entity Framework remova automaticamente e recrie o banco de dados usando o novo esquema de classe de modelo. Essa abordagem é conveniente no início do ciclo de desenvolvimento, pois ela permite que você desenvolva rapidamente o modelo e o esquema de banco de dados juntos. A desvantagem é que você perde os dados existentes no banco de dados. Não use essa abordagem em um banco de dados de produção. A remoção do banco de dados em alterações de esquema e o uso de um inicializador para propagar automaticamente o banco de dados com os dados de teste é muitas vezes uma maneira produtiva de desenvolver um aplicativo.

  2. Modifique explicitamente o esquema do banco de dados existente para que ele corresponda às classes de modelo. A vantagem dessa abordagem é manter os dados. Faça essa alteração manualmente ou criando um script de alteração de banco de dados.

  3. Use as Migrações do Code First para atualizar o esquema de banco de dados.

Para este tutorial, use as Migrações do Code First.

Atualize a classe SeedData para que ela forneça um valor para a nova coluna. Uma alteração de amostra é mostrada abaixo, mas faça essa alteração em cada bloco new Movie.

context.Movie.AddRange(
    new Movie
    {
        Title = "When Harry Met Sally",
        ReleaseDate = DateTime.Parse("1989-2-12"),
        Genre = "Romantic Comedy",
        Price = 7.99M,
        Rating = "R"
    },

Consulte o arquivo SeedData.cs concluído.

Compile a solução.

Adicionar uma migração para o campo de classificação

  1. No menu Ferramentas, selecione Gerenciador de Pacotes NuGet > Console do Gerenciador de Pacotes.

  2. No PMC, insira os seguintes comandos:

    Add-Migration Rating
    Update-Database
    

O comando Add-Migration informa à estrutura:

  • Compare o modelo de Movie com o esquema de banco de dados Movie.
  • Crie código para migrar o esquema de banco de dados para o novo modelo.

O nome “Classificação” é arbitrário e é usado para nomear o arquivo de migração. É útil usar um nome significativo para o arquivo de migração.

O comando Update-Database informa à estrutura para aplicar as alterações de esquema ao banco de dados e preservar os dados existentes.

Se você excluir todos os registros no banco de dados, o inicializador propagará o banco de dados e incluirá o campo Rating. Faça isso com os links Excluir no navegador ou no SSOX (Pesquisador de Objetos do SQL Server).

Outra opção é excluir o banco de dados e usar as migrações para recriar o banco de dados. Para excluir o banco de dados no SSOX:

  • Selecione o banco de dados no SSOX.

  • Clique com o botão direito do mouse no banco de dados e selecione Excluir.

  • Marque Fechar conexões existentes.

  • Selecione OK.

  • No PMC, atualize o banco de dados:

    Update-Database
    

Execute o aplicativo e verifique se você pode criar/editar/exibir filmes com um campo Rating. Se o banco de dados não for propagado, defina um ponto de interrupção no método SeedData.Initialize.

Próximas etapas