22 de enero de 2013

ASP.NET MVC Helper. Html.DropDownListFor con Enumeración (enum)

 

El objetivo de este pequeño post es ver como mostrar un combo box en ASP.NET MVC que se llena desde un enumerado (enum).

El enumerado que usaremos en nuestro ejemplo es el siguiente:

public enum ResultsOrderBy

{

       [Description("Precio")]

       PrecioMenorPrimero,

 

       [Description("Solo en stock")]

       SoloEnStock,

 

       [Description("Más vendidos")]

       MasVendidos

}

Además asumiremos que el modelo usado por la vista tiene una propiedad llamada (OrderBy) que es del tipo (ResultsOrderBy).

Para lograr nuestro objetivo usaremos el helper (Html.DropDownListFor) con dos variantes:

  1. La primera y más sencilla mostrará los valores del enumerado (enum).
  2. La segunda variante, un poco más lograda, mostrará el valor del atributo “Description” de cada uno de los valores del enumerado (enum).

Ver imagen:

Captura1Captura2

 

@Html.DropDownListFor. Variante 1:

Esta variante es muy simple de usar, basta con usar el método Enum.GetValues.

@Html.DropDownListFor(m => m.OrderBy,

    new SelectList(Enum.GetValues(typeof(ResultsOrderBy))),

    new { id = "cmbOrderBy" })

La desventaja de usar esta variante es que nos muestra los valores del enumerado (enum) y no su descripción (ver imagen anterior resaltada en amarillo)

 

 

@Html.DropDownListFor. Variante 2:

Esta variante es un`poco mas compleja y tendremos que hacer uso de algunos métodos extensores implementados por nosotros. Veamos primero el uso del (@Html.DropDownListFor) y posteriormente veremos los métodos necesarios.

@Html.DropDownListFor(m => m.OrderBy,

    (SelectList)(typeof(ResultsOrderBy).GetSelectList()),

    new { id = "cmbOrderBy" })

En esta variante vemos que hacemos uso del método extensor (GetSelectList) que a su ves usa (GetKeyValueList), además necesitaremos una clase muy sencilla (KeyValue) veamos sus implementaciones:

public partial class KeyValue

{

       public KeyValue(){}

       public KeyValue(string key, string value)

       {

             Key = key;

             Value = value;

       }

 

       public string Key { get; set; }

       public string Value { get; set; }

}

El método GetSelectList:

public static SelectList GetSelectList(this Type enumType)

{

       var result = new SelectList(enumType.GetKeyValueList(), "Key", "Value");

       return result;

}

El método GetKeyValueList:

public static IList<KeyValue> GetKeyValueList(this Type enumType)

{

       var arrValores = Enum.GetValues(enumType);

       var lstEnumDescripcion = new List<KeyValue>();

 

       foreach (var valor in arrValores)

       {

             FieldInfo fieldInfo = enumType.GetField(valor.ToString());

             var attribs = fieldInfo

                    .GetCustomAttributes(typeof(DescriptionAttribute), false)

                    as DescriptionAttribute[];

 

             var descripcion = (attribs == null || attribs.Length == 0) ?

                    valor.ToString() :

                    attribs[0].Description;

 

             lstEnumDescripcion.Add(

                    new KeyValue(valor.GetHashCode().ToString(), descripcion));

       }

 

       return lstEnumDescripcion;

}

Y listo… espero les sea de utilidad.

15 de enero de 2013

EF Code First Migrations

Hace unos días escribí un articulo “EF 5 Code First (Entity Framework Code First)” que deberías leer antes que este. En aquel articulo explicaba como usar EF 5 Code First, en esta nueva entrada pretendo hablarles brevemente sobre:

  1. EF Code First Migrations. Migraciones manuales.
  2. EF Code First Migrations. Migraciones automáticas.
  3. EF Code First Migrations. Otras consideraciones.

 

EF Code First Migrations. Migraciones manuales.

EF Code First Migrations, no es otra cosa que habilitar la capacidad de actualizar la base de datos con los cambios realizados en nuestras entidades de código (POCO)… pero veamos un ejemplo.

Sigamos con el mismo ejemplo del articulo anterior “EF 5 Code First (Entity Framework Code First)”, en el que teníamos una entidad Persona:

namespace AppEjemploEfCodeFirst.Data.Entities

{

       public partial class Persona

       {

             public int PersonaId { get; set; }

             public string Nombre { get; set; }

             public string Apellidos { get; set; }

             public DateTime FechaNacimiento { get; set; }

       }

}

Imaginemos que deseamos agregar una nueva propiedad, por ejemplo …. Numero de Documento, quedando así la nueva clase:

namespace AppEjemploEfCodeFirst.Data.Entities

{

       public partial class Persona

       {

             public int PersonaId { get; set; }

             public string Nombre { get; set; }

             public string Apellidos { get; set; }

             public DateTime FechaNacimiento { get; set; }

             public string DocumentoNo { get; set; }

       }

}

Si ejecutamos ahora la aplicación, recibiríamos un error como el siguiente:

image

Este error se debe a que no tenemos activada las migraciones (EF Code First Migrations) que por defecto viene desactivada, al menos de las versiones 4.3 a la 5.0 de EF. Pero no hay que preocuparse, habilitarla es muy simple, veamos como:

Pasos para habilitar EF Code First Migrations:

  1. Ir al menú Herramienta / Administrador de paquetes de biblioteca / Consola del Administrador de paquetes.
  2. Estando en la consola (importantísimo) escoger el proyecto al cual queremos habilitarle la migración (AppEjemploEfCodeFirst.Data).
  3. Escribir el siguiente comando en la consola (Enable-Migrations) y presionar “enter”. Con esto hemos habilitado la migración manual, mas adelante veremos la migración automática. Podrás observar que en el proyecto escogido para habilitarle la migración (EF Code First Migrations) se ha creado una nueva carpeta (Migrations), aunque no es necesario puedes ojear un poco en los archivos creados para llevarte una idea de lo que esta sucediendo.
  4. Escribir en la consola (Add-Migration Migracion1Prueba) la palabra Migracion1Prueba es un nombre cualquiera para identificar la migración.
  5. Y por ultimo escribimos otro comando en la consola (Update-Database). Ya tendríamos el modelo de base de datos actualizado con los cambios realizados en las entidades.

image

 

 

EF Code First Migrations. Migraciones automáticas.

Entity Framework te brinda además la posibilidad de que las migraciones se realicen de forma automática, así nos ahorraríamos el tener que ir a la Consola del Administrador de paquetes y escribir estos 2 comandos:

  • Add-Migration
  • Update-Database

Veamos como hacerlo:

Primero debemos ir a la clase (Configuration) y modificar la siguiente línea de código del Constructor:

public Configuration()

{

AutomaticMigrationsEnabled = true;

}

 

Después debemos registrar el inicializador MigrateDatabaseToLatestVersion. Para ello escribimos el siguiente código en el Global.asax, método Application_Start (o cualquier otro punto de entrada de nuestra aplicación);

Database.SetInitializer(new                             MigrateDatabaseToLatestVersion<AppEjemploEfCodeFirstDbContext, Configuration>());

Y con esto todo listo, ya puedes hacer cualquier modificación en el código (clases POCO) y después de ejecutar la aplicación, los cambios serán migrados a la base de datos.

Consideraciones a tener en cuenta:

  • Puede que necesites cambiar el nivel de accesibilidad de la clase (Configuration)
  • Puede que tengas que agregar algunos (Namespace) al Global.asax.

 

EF Code First Migrations. Otras consideraciones.

Puede que se te presenten ciertos escenarios donde no se apliquen las migraciones automáticas. Por ejemplo cuando eliminas una columna o eliminas una entidad (tabla de datos).

No se ha aplicado la migración automática porque podría ocasionar una pérdida de datos.

En estos casos tendrás (al menos hasta la versión actual) que forzar la migración de forma manual, para ello escribirás el siguiente comando en la consola:

Update-Database -Force -Verbose

Existen además algunos casos en los que no es suficiente, pongamos un ejemplo: Imagina que tienes una entidad con una propiedad (public long Id { get; set; }) y decides cambiar el tipo a entero (public int Id { get; set; }).

En el caso anterior no basta con forzar la actualización. En este caso, mi consejo es que quites la entidad del modelo (o la propiedad) y fuerces la actualización (Update-Database -Force -Verbose), con esto se eliminará la tabla de datos, vuelves a incluir la entidad y nuevamente fuerzas la actualización para que cree la tabla con el nuevo tipo deseado.

 

Artículos relacionados: