En este artículo mostraré como usar tipos enum con Entity Framework Code First, además de mostrar cómo usar enums en una consulta LINQ.
El soporte de enumeraciones fue introducido en Entity Framework 5. Para usar todas las nuevas características que trae el EF 5.0 (como enumeraciones, tipos de datos espaciales y funciones tabulares), debe configurar el proyecto para que utilice la versión .NET Framework 4.5. Recordemos que Visual Studio 2012, por defecto, utiliza .NET 4.5.
Por este motivo no se puede utilizar el Visual Studio 2010 para aplicar estas nuevas características, aun cuando estemos utilizando la versión Entity Framework 5.0.
En Entity Framework, una enumeración puede tener los siguientes tipos subyacentes: Byte, Int16, Int32, Int64 o SByte.
Creación de la aplicación ejemplo
-
Abrimos Visual Studio 2012
-
En el menú File, hacemos click en New, y luego en Project
-
En la ventana New Project, en el panel izquierdo, hacemos click en Visual C#, y luego seleccionamos la plantilla Console Application
-
Entramos SoporteEnumCodeFirst como el nombre del proyecto y luego hacemos click en OK
-
Definimos un nuevo modelo de datos usando Code First, para eso, agregamos una nueva clase a nuestro proyecto, llamada Course y dentro de este archivo, además agregamos la enumeración CourseNames. El archivo completo es el siguiente:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SoporteEnumCodeFirst
{
public enum CourseNames
{
[Description("MVC 4")] MVC4 = 10285,
[Description("HTML 5")] HTML5 = 10286,
[Description("Windows Comunication Foundation")] WCF = 10287,
[Description("Entity Framework 5.0")] EntityFramework5 = 10288
}
public class Course
{
public int CourseId { get; set; }
public CourseNames Name { get; set; }
public Byte DuracionDias { get; set; }
}
}
-
Definimos el contexto, es decir una clase, llamada EnumContext, derivada de DbContext, para eso, agregamos una referencia al assembly EntityFramework (ya que las clases DbContext y DbSet están definidas en este assembly), utilizando el paquete NuGet EntityFramework. Al hacer esto, además de agregar el assembly EntityFramework, también son agregadas referencias a los assemblies System.ComponentModel.DataAnnotations y System.Data.Entity. Arriba del código de la clase EnumContext escribimos la sentencia using que importa el namespace System.Data.Entity. El código de la clase EnumContext queda definido así:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
namespace SoporteEnumCodeFirst
{
public partial class EnumContext : DbContext
{
public EnumContext():base("EF5EnumDB")
{ }
public DbSet Courses { get; set; }
}
}
Como vemos en el código de arriba, generaremos la base de datos con el nombre EF5EnumDB. Esto se obtiene llamando al constructor de la clase base (DbContext), pasándole el nombre que queremos darle a la base de datos como parámetro.
-
En el archivo Program.cs, agregamos el siguiente código a la función Main. El código agrega un nuevo objeto del tipo curso al contexto y luego graba los datos. Por último el código también ejecuta una consulta LINQ que devuelve un curso donde el nombre del curso es el valor de la enumeración CourseNames.EntityFramework5. A continuación el código completo de la clase Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SoporteEnumCodeFirst
{
class Program
{
static void Main(string[] args)
{
using (var db = new EnumContext())
{
db.Courses.Add(new Course {
Name = CourseNames.EntityFramework5,
DuracionDias=10 });
db.SaveChanges();
var miCurso =
(from d in db.Courses
where d.Name == CourseNames.EntityFramework5
select d).FirstOrDefault();
Console.WriteLine("CourseID: {0} Nombre: {1}",
miCurso.CourseId, miCurso.Name);
}
}
public static string GetDescription(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes =
(DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
return (attributes.Length > 0) ?
attributes[0].Description :
value.ToString();
}
}
}
Al ejecutar el programa, se obtiene la salida que se observa en el Figura 1:
|
Figura 1 - Salida del programa con soporte para Enumeraciones para EF 5 Code First |
Como observamos en la figura 2, si abrimos el SQL Management Studio, comprobaremos que efectivamente, se creo una nueva base de datos con el nombre EF5EnumDB y que dicha base de datos tiene una tabla llamada Courses y el campo Name se definió como un int
|
Figura 2 - La base de datos creada, se generó con una tabla Courses y el campo Name es
del tipo int |
En la figura 3 observamos que el valor insertado en el campo Name es precisamente el valor numérico definido en la enumeración (para nuestro caso 10288)
|
Figura 3 - El valor insertado en el campo Name es el valor numérico definido en la enumeración |
Una aclaración sobre las enumeraciones: Los miembros de una enumeración deben ser
identificadores válidos, por lo que no pueden contener espacios o caracteres especiales. Pero... y si queremos recuperar los miembros de la enumeración con espacios y caracteres especiales... ¿qué debemos hacer?
Como se ve en el
código de la definición de la enumeración, esto lo podemos lograr utilizando la clase
DescriptionAttribute, pasándole una descripción completa de cada valor de la enumeración (por ejemplo para el valor "
EntityFramework5", le pasamos "
Entity Framework 5.0" o para "
WCF", le pasamos "
Windows Communication Foundation".
Para recuperar la descripción, usamos
Reflexión, como se ve en el código de la función
GetDescription(Enum value)