Compartilhar via


Adicionar um novo campo ao modelo de filme e à tabela

por Rick Anderson

Observação

Uma versão atualizada deste tutorial está disponível aqui que usa ASP.NET MVC 5 e Visual Studio 2013. É mais seguro, muito mais simples de seguir e demonstra mais recursos.

Nesta seção, você usará as Migrações do Code First do Entity Framework para migrar algumas alterações nas classes de modelo para que a alteração seja aplicada ao banco de dados.

Por padrão, quando você usa o Entity Framework Code First para criar automaticamente um banco de dados, como fez anteriormente neste tutorial, o Code First adiciona uma tabela ao banco de dados para ajudar a controlar se o esquema do banco de dados está em sincronia com as classes de modelo das quais ele foi gerado. Se eles não estiverem sincronizados, o Entity Framework gerará um erro. Isso facilita o rastreamento de problemas no tempo de desenvolvimento que, de outra forma, você só encontraria (por erros obscuros) em tempo de execução.

Configurando migrações do Code First para alterações de modelo

Se você estiver usando o Visual Studio 2012, clique duas vezes no arquivo Movies.mdf do Gerenciador de Soluções para abrir a ferramenta de banco de dados. O Visual Studio Express para Web mostrará o Gerenciador de Banco de Dados, o Visual Studio 2012 mostrará o Gerenciador de Servidores. Se você estiver usando o Visual Studio 2010, use o Pesquisador de Objetos do SQL Server.

Na ferramenta de banco de dados (Explorador de Banco de Dados, Gerenciador de Servidores ou Pesquisador de Objetos do SQL Server), clique com o botão direito do MovieDBContext mouse e selecione Excluir para descartar o banco de dados de filmes.

Captura de tela que mostra a janela do Gerenciador de Servidores. Excluir é selecionado no menu do botão direito do mouse Contexto D B do filme.

Navegue de volta para o Gerenciador de Soluções. Clique com o botão direito do mouse no arquivo Movies.mdf e selecione Excluir para remover o banco de dados de filmes.

Captura de tela que mostra a janela do Gerenciador de Soluções. Excluir é selecionado no menu do botão direito do mouse em Filmes dot m d f.

Compile o aplicativo para verificar se não existem erros.

No menu Ferramentas, clique em Gerenciador de Pacotes NuGet e, em seguida, em Console do Gerenciador de Pacotes.

Adicionar Pack Man

Na janela Console do Gerenciador de Pacotes , no prompt, PM> insira "Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext".

Captura de tela que mostra a janela do Console do Gerenciador de Pacotes. O comando Ativar migrações é inserido.

O comando Enable-Migrations (mostrado acima) cria um arquivo Configuration.cs em uma nova pasta Migrations .

Captura de tela que mostra a janela do Gerenciador de Soluções. A pasta Migrações e o arquivo Configuration dot c s estão circulados em vermelho.

O Visual Studio abre o arquivo Configuration.cs . Substitua o Seed método no arquivo Configuration.cs pelo seguinte código:

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

Clique com o botão direito do mouse na linha ondulada vermelha abaixo Movie e selecione Resolver e usando MvcMovie.Models;

Captura de tela que mostra Resolver selecionado no menu do botão direito do mouse Filme.

Isso adiciona a seguinte instrução using:

using MvcMovie.Models;

Observação

As Migrações do Code First chamam o Seed método após cada migração (ou seja, chamando update-database no Console do Gerenciador de Pacotes) e esse método atualiza as linhas que já foram inseridas ou as insere se ainda não existirem.

Pressione CTRL-SHIFT-B para criar o projeto.(As etapas a seguir falharão se você não compilar neste momento.)

A próxima etapa é criar uma DbMigration classe para a migração inicial. Essa migração para cria um novo banco de dados, é por isso que você excluiu o arquivo movie.mdf em uma etapa anterior.

Na janela Console do Gerenciador de Pacotes , insira o comando "add-migration Initial" para criar a migração inicial. O nome "Inicial" é arbitrário e é usado para nomear o arquivo de migração criado.

Captura de tela que mostra a janela do Console do Gerenciador de Pacotes. O parágrafo que começa com O Código do Designer para este arquivo de migração é realçado.

As Migrações do Code First criam outro arquivo de classe na pasta Migrações (com o nome {DateStamp}_Initial.cs ), e essa classe contém código que cria o esquema de banco de dados. O nome do arquivo de migração é previamente corrigido com um carimbo de data/hora para ajudar com a ordenação. Examine o arquivo {DateStamp}_Initial.cs , ele contém as instruções para criar a tabela Filmes para o banco de dados de filmes. Quando você atualiza o banco de dados nas instruções abaixo, esse arquivo {DateStamp}_Initial.cs é executado e cria o esquema de banco de dados. Em seguida, o método Seed será executado para preencher o banco de dados com dados de teste.

No Console do Gerenciador de Pacotes, insira o comando "update-database" para criar o banco de dados e executar o método Seed .

Captura de tela que mostra a janela do Console do Gerenciador de Pacotes. O comando update database é inserido.

Se você receber um erro que indica que uma tabela já existe e não pode ser criada, provavelmente é porque você executou o aplicativo depois de excluir o banco de dados e antes de executar update-database. Nesse caso, exclua o arquivo Movies.mdf novamente e tente novamente o update-database comando. Se você ainda receber um erro, exclua a pasta de migrações e o conteúdo e comece com as instruções na parte superior desta página (ou seja, exclua o arquivo Movies.mdf e prossiga para Enable-Migrations).

Execute o aplicativo e navegue até a URL / Movies . Os dados de semente são exibidos.

Captura de tela que mostra a página do Índice de Filmes MVC com uma lista de quatro filmes.

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

Comece adicionando uma nova Rating propriedade à classe existente Movie . Abra o arquivo Models\Movie.cs e adicione a Rating propriedade como esta:

public string Rating { get; set; }

A classe completa Movie agora se parece com o seguinte código:

public class Movie
{
    public int ID { get; set; }
    public string Title { get; set; }
    public DateTime ReleaseDate { get; set; }
    public string Genre { get; set; }
    public decimal Price { get; set; }
    public string Rating { get; set; }
}

Compile o aplicativo usando o comando de menu Build>Build Movie ou pressionando CTRL-SHIFT-B.

Agora que você atualizou a Model classe, também precisa atualizar os modelos de exibição \Views\Movies\Index.cshtml e \Views\Movies\Create.cshtml para exibir a nova Rating propriedade no modo de exibição do navegador.

Abra o arquivo \Views\Movies\Index.cshtml e adicione um título de <th>Rating</th> coluna logo após a coluna Preço . Em seguida, adicione uma <td> coluna perto do final do modelo para renderizar o @item.Rating valor. Abaixo está a aparência do modelo de exibição Index.cshtml atualizado:

@model IEnumerable<MvcMovie.Models.Movie>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<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>

Em seguida, abra o arquivo \Views\Movies\Create.cshtml e adicione a marcação a seguir perto do final do formulário. Isso renderiza uma caixa de texto para que você possa especificar uma classificação quando um novo filme é criado.

<div class="editor-label">
    @Html.LabelFor(model => model.Rating)
</div>
<div class="editor-field">
    @Html.EditorFor(model => model.Rating)
    @Html.ValidationMessageFor(model => model.Rating)
</div>

Agora você atualizou o código do aplicativo para dar suporte à nova Rating propriedade.

Agora execute o aplicativo e navegue até o URL /Movies . Ao fazer isso, porém, você verá um dos seguintes erros:

Captura de tela que mostra o erro Exceção de operação inválida não foi tratada pelo código do usuário.

Captura de tela que mostra a janela do navegador com um erro que indica Erro do servidor no aplicativo.

Você está vendo esse erro porque a classe de modelo atualizada Movie no aplicativo agora é diferente do esquema da Movie tabela do banco de dados existente. (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 com base no novo esquema de classe de modelo. Essa abordagem é muito conveniente ao fazer o desenvolvimento ativo em um banco de dados de teste; Ele permite que você evolua rapidamente o modelo e o esquema de banco de dados juntos. A desvantagem, porém, é que você perde os dados existentes no banco de dados — portanto, não deseja usar essa abordagem em um banco de dados de produção! Usar um inicializador para propagar automaticamente um banco de dados com dados de teste geralmente é uma maneira produtiva de desenvolver um aplicativo. Para obter mais informações sobre inicializadores de banco de dados do Entity Framework, consulte o tutorial ASP.NET MVC/Entity Framework de Tom Dykstra.
  2. Modifique explicitamente o esquema do banco de dados existente para que ele corresponda às classes de modelo. A vantagem dessa abordagem é que você mantém 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, usaremos as Migrações do Code First.

Atualize o método Seed para que ele forneça um valor para a nova coluna. Abra o arquivo Migrations\Configuration.cs e adicione um campo Rating a cada objeto Movie.

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

Compile a solução e, em seguida, abra a janela Console do Gerenciador de Pacotes e insira o seguinte comando:

add-migration AddRatingMig

O add-migration comando informa à estrutura de migração para examinar o modelo de filme atual com o esquema de banco de dados de filme atual e criar o código necessário para migrar o banco de dados para o novo modelo. O AddRatingMig é arbitrário e é usado para nomear o arquivo de migração. É útil usar um nome significativo para a etapa de migração.

Quando esse comando for concluído, o Visual Studio abrirá o arquivo de classe que define a nova DbMigration classe derivada e, no Up método, você poderá ver o código que cria a nova coluna.

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

Compile a solução e insira o comando "update-database" na janela Console do Gerenciador de Pacotes .

A imagem a seguir mostra a saída na janela Console do Gerenciador de Pacotes (o carimbo de data anterior AddRatingMig será diferente.)

Captura de tela que mostra o comando update database.

Execute novamente o aplicativo e navegue até a URL /Movies. Você pode ver o novo campo Classificação.

Captura de tela que mostra a página do Índice de Filmes MVC com quatro filmes listados.

Clique no link Criar novo para adicionar um novo filme. Observe que você pode adicionar uma classificação.

7_CreateRioII

Clique em Criar. O novo filme, incluindo a classificação, agora aparece na lista de filmes:

7_ourNewMovie_SM

Você também deve adicionar o Rating campo aos modelos de exibição Editar, Detalhes e SearchIndex.

Você pode inserir o comando "update-database" na janela do Console do Gerenciador de Pacotes novamente e nenhuma alteração será feita, pois o esquema corresponde ao modelo.

Nesta seção, você viu como modificar objetos de modelo e manter o banco de dados em sincronia com as alterações. Você também aprendeu uma maneira de preencher um banco de dados recém-criado com dados de exemplo para que possa experimentar cenários. Em seguida, vamos ver como você pode adicionar uma lógica de validação mais avançada às classes de modelo e permitir que algumas regras de negócios sejam impostas.