Agregar un nuevo campo a la tabla y modelo de películas (C#)

por Rick Anderson

Nota:

Aquí hay disponible una versión actualizada de este tutorial en la que se usa ASP.NET MVC 5 y Visual Studio 2013. Es más segura, mucho más sencilla de seguir y muestra más características.

Este tutorial le enseñará los conceptos básicos de la creación de una aplicación web ASP.NET MVC mediante Microsoft Visual Web Developer 2010 Express Service Pack 1, que es una versión gratuita de Microsoft Visual Studio. Antes de empezar, asegúrese de que ha instalado los requisitos previos que se enumeran a continuación. Para instalarlos todos, haga clic en el vínculo siguiente: Instalador de plataforma web. Como alternativa, puede instalar individualmente los requisitos previos mediante los vínculos siguientes:

Si usa Visual Studio 2010 en lugar de Visual Web Developer 2010, para instalar los requisitos previos haga clic en el vínculo siguiente: Requisitos previos de Visual Studio 2010.

Un proyecto de Visual Web Developer con código fuente de C# está disponible para acompañar este tema. Descargue la versión de C#. Si prefiere Visual Basic, cambie a la versión de Visual Basic de este tutorial.

En esta sección, realizará algunos cambios en las clases de modelo y aprenderá a actualizar el esquema de la base de datos para que coincida con los cambios del modelo.

Adición de una propiedad de clasificación al modelo Movie

Para empezar, agregue una nueva propiedad Rating a la clase Movie existente. Abra el archivo Movie.cs y agregue la propiedad Rating como esta:

public string Rating { get; set; }

La clase Movie completa ahora tiene el siguiente aspecto:

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

Vuelva a compilar la aplicación mediante el comando de menú Depurar>Compilar película.

Ahora que ha actualizado la clase Model, también debe actualizar las plantillas de vista \Views\Movies\Index.cshtml y \Views\Movies\Create.cshtml para admitir la nueva propiedad Rating.

Abra el archivo \Views\Movies\Index.cshtml y agregue un encabezado de columna <th>Rating</th> justo después de la columna Price. Después, agregue una columna <td> cerca del final de la plantilla para representar el valor @item.Rating. A continuación se muestra el aspecto de la plantilla de vista Index.cshtml actualizada:

<table>
    <tr>
        <th></th>
        <th>Title</th>
        <th>Release Date</th>
        <th>Genre</th>
        <th>Price</th>
        <th>Rating</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 Me", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}
</table>

A continuación, abra el archivo \Views\Movies\Create.cshtml y agregue el siguiente marcado cerca del final del formulario. Esto representa un cuadro de texto para que pueda especificar una clasificación cuando se crea una película.

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

Administración de diferencias entre el esquema de base de datos y el modelo

Ahora ha actualizado el código de la aplicación para admitir la nueva propiedad Rating.

Ejecute la aplicación y vaya a la dirección URL /Movies. Pero al hacerlo, verá el siguiente error:

Screenshot that shows the browser window with an error that states Server Error in Application.

Este error se muestra porque la clase del modelo Movie actualizada en la aplicación es diferente del esquema de la tabla Movie de la base de datos existente. (No hay ninguna columna Rating en la tabla de la base de datos).

De manera predeterminada, cuando usa Code First de Entity Framework para crear una base de datos de forma automática como antes en este tutorial, Code First agrega una tabla a la base de datos para ayudar a saber si el esquema de la base de datos está sincronizado con las clases del modelo a partir del que se ha generado. Si no están sincronizados, Entity Framework genera un error. Esto facilita el seguimiento de los problemas en tiempo de desarrollo que, de lo contrario, solo se pueden encontrar (por errores ocultos) en tiempo de ejecución. La característica de comprobación de sincronización es lo que hace que se muestre el mensaje de error que acaba de ver.

Hay dos enfoques para resolver este error:

  1. Haga que Entity Framework quite de forma automática la base de datos y la vuelva a crear basándose en el nuevo esquema de la clase del modelo. Este enfoque resulta muy conveniente cuando se realiza el desarrollo activo en una base de datos de prueba; ya que permite desarrollar rápidamente el esquema del modelo y la base de datos de manera conjunta. Pero la desventaja es que se pierden los datos existentes en la base de datos, así que no use este enfoque en una base de datos de producción.
  2. Modifique explícitamente el esquema de la base de datos existente para que coincida con las clases del modelo. La ventaja de este enfoque es que se conservan los datos. Puede realizar este cambio de forma manual o mediante la creación de un script de cambio de base de datos.

En este tutorial, usará el primer enfoque: hará que Code First de Entity Framework vuelva a crear automáticamente la base de datos siempre que cambie el modelo.

Recreación automática de la base de datos cuando cambia el modelo

Ahora se actualizará la aplicación para que Code First quite y vuelva a crear automáticamente la base de datos cada vez que cambie el modelo de la aplicación.

Nota:

Advertencia Debe habilitar este enfoque para quitar y volver a crear automáticamente la base de datos solo cuando use una base de datos de desarrollo o prueba, y nunca en una base de datos de producción que contenga datos reales. Su uso en un servidor de producción puede provocar la pérdida de datos.

En el Explorador de soluciones, haga clic con el botón derecho en la carpeta Models, seleccione Agregar y después Clase.

Screenshot that shows the Solution Explorer window. Add is selected in the Models right click menu. Class is selected in the sub menu.

Asigne el nombre "MovieInitializer" a la clase. Actualice la clase MovieInitializer para que contenga el código siguiente:

using System;
using System.Collections.Generic;
using System.Data.Entity;

namespace MvcMovie.Models {
    public class MovieInitializer : DropCreateDatabaseIfModelChanges<MovieDBContext> {
        protected override void Seed(MovieDBContext context) {
            var movies = new List<Movie> {  
  
                 new Movie { Title = "When Harry Met Sally",   
                             ReleaseDate=DateTime.Parse("1989-1-11"),   
                             Genre="Romantic Comedy",  
                             Rating="R",  
                             Price=7.99M},  

                     new Movie { Title = "Ghostbusters ",   
                             ReleaseDate=DateTime.Parse("1984-3-13"),   
                             Genre="Comedy",  
                              Rating="R",  
                             Price=8.99M},   
  
                 new Movie { Title = "Ghostbusters 2",   
                             ReleaseDate=DateTime.Parse("1986-2-23"),   
                             Genre="Comedy",  
                             Rating="R",  
                             Price=9.99M},   

               new Movie { Title = "Rio Bravo",   
                             ReleaseDate=DateTime.Parse("1959-4-15"),   
                             Genre="Western",  
                             Rating="R",  
                             Price=3.99M},   
             };

            movies.ForEach(d => context.Movies.Add(d));
        }
    }
}

La clase MovieInitializer especifica que la base de datos usada por el modelo se debe quitar y volver a crear automáticamente si las clases del modelo cambian alguna vez. El código incluye un método Seed para especificar algunos datos predeterminados que se van a agregar automáticamente a la base de datos siempre que se cree (o se vuelva a crear). Esto proporciona una manera útil de rellenar la base de datos con algunos datos de ejemplo, sin necesidad de rellenarla manualmente cada vez que realice un cambio del modelo.

Ahora que ha definido la clase MovieInitializer, querrá conectarla para que cada vez que se ejecute la aplicación, compruebe si las clases del modelo son diferentes del esquema de la base de datos. Si lo son, puede ejecutar el inicializador a fin de volver a crear la base de datos para que coincida con el modelo y, después, rellenar la base de datos con los datos de ejemplo.

Abra el archivo Global.asax que se encuentra en la raíz del proyecto MvcMovies:

Screenshot that shows the Global dot asax dot c s tab. Global dot asax is circled in red in the Solution Explorer window.

El archivo Global.asax contiene la clase que define toda la aplicación para el proyecto y contiene un controlador de eventos Application_Start que se ejecuta cuando se inicia la aplicación por primera vez.

Agregue dos instrucciones using en la parte superior del archivo. La primera hace referencia al espacio de nombres de Entity Framework y la segunda al espacio de nombres donde reside la clase MovieInitializer:

using System.Data.Entity;            // Database.SetInitialize
using MvcMovie.Models;              // MovieInitializer

Después, busque el método Application_Start y agregue una llamada a Database.SetInitializer al principio del método, como se muestra a continuación:

protected void Application_Start()
{
    Database.SetInitializer<MovieDBContext>(new MovieInitializer());

    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

La instrucción Database.SetInitializer que acaba de agregar indica que la base de datos usada por la instancia de MovieDBContext se debe eliminar y volver a crear automáticamente si el esquema y la base de datos no coinciden. Y como ha visto, también rellenará la base de datos con los datos de ejemplo especificados en la clase MovieInitializer.

Cierre el archivo Global.asax.

Vuelva a ejecutar la aplicación y vaya a la dirección URL /Movies. Cuando se inicia la aplicación, detecta que la estructura del modelo ya no coincide con el esquema de la base de datos. Vuelve a crear automáticamente la base de datos para que coincida con la nueva estructura del modelo y rellena la base de datos con las películas de ejemplo:

7_MyMovieList_SM

Haga clic en el vínculo Crear nueva para agregar una nueva película. Tenga en cuenta que puede agregar una clasificación.

7_CreateRioII

Haga clic en Crear. La nueva película, incluida la clasificación, ahora aparece en la lista de películas:

7_ourNewMovie_SM

En esta sección ha visto cómo puede modificar objetos de modelo y mantener la base de datos sincronizada con los cambios. También ha aprendido a rellenar una base de datos recién creada con datos de ejemplo para probar escenarios. A continuación, verá cómo puede agregar lógica de validación más completa a las clases de modelo y permitir que se apliquen algunas reglas de negocios.