La principal ventaja de usar clases POCO es que el modelo de clases es más limpio ya que las clases no tiene ninguna dependencia con el Entity Framework (clase EntityObject). Por defecto se utiliza el nombre de nuestras clases y correspondientes propiedades para generar los nombre de tablas y campos. Esto puede ser más que suficiente para muchos proyectos, sobre todo si están empezando de cero, pero, ¿que ocurre si queremos hacer modificaciones en nuestro modelo de datos? Para eso tenemos dos alternativas
- Data Annotations
- Fluent Api
donde escribiremos
Install-Package EntityFramework -Version 4.3.1Si todo ha ido bien veremos algo parecido a esto
Ya tenemos la última versión del Entity Framework instalada en nuestro proyecto, así que, ¿ahora qué? Para demostrar el uso de Fluent Api para definir nuestro modelo de datos, voy a usar la estructura que podría tener un blog (muy simplificado). Para estos tendremos
- Un blog con su identificador y título.
- Una lista de post asociada a nuestro blog. Cada post tendrá su identificador, titulo, un título en html y un texto.
- Cada post pertenecerá a una categoría y podrá tener una lista de etiquetas (tags). Tanto las categorías como las etiquetas, tendrán tanto un identificador como un nombre.
Con este esquema tan simple crearemos nuestras clases de la siguiente manera.
public class Blog { public int IdBlog { get; set; } public string Title { get; set; } // Navigation properties public virtual ICollection<Post> Posts { get; set; } } public class Post { public int IdPost { get; set; } public string Title { get; set; } public string HtmlTitle { get; set; } public string Body { get; set; } // Foreign key public int IdBlog { get; set; } // Navigation properties public virtual Blog Blog { get; set; } public virtual Category Category { get; set; } public virtual ICollection<Tag> Tags { get; set; } } public class Category { public int IdCategory { get; set; } public string Name { get; set; } // Navigation properties public virtual ICollection<Post< Posts { get; set; } } public class Tag { public int IdTag { get; set; } public string Name { get; set; } // Navigation properties public virtual ICollection<Post> Posts { get; set; } }
Una vez hecho esto empezaremos a definir nuestro contexto de la siguiente manera
public class DataContext : DbContext { }Ahora definiremos un constructor donde especificaremos el nombre de la cadena de conexión y el conjunto de entidades que serán mapeadas (en nuestro caso todas)
public class DataContext : DbContext { public DataContext() : base("DataContext") { } public DbSet<Blog> Blog { get; set; } public DbSet<Post> Post { get; set; } public DbSet<Category> Category { get; set; } public DbSet<Tag> Tag { get; set; } }Lo siguiente que debemos hacer es definir nuestro modelo de datos, por ejemplo, definiendo cuales son las claves de nuestras tablas. Para estas definiciones usaremos la sintaxis que nos brinda Fluent Api, así que, sobreescribiremos el método OnModelCreating de nuestro DataContext y escribiremos lo siguiente para definir nuestras claves primarias
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Primary Keys modelBuilder.Entity<Blog>().HasKey(c => c.IdBlog); modelBuilder.Entity<Post>().HasKey(c => c.IdPost); modelBuilder.Entity<Category>().HasKey(c => c.IdCategory); modelBuilder.Entity<Tag>().HasKey(c => c.IdTag); }Con este código "casi" ya podríamos crear nuestro primer modelo de datos, y ver como funciona Code First con Fluent Api. Tan solo deberíamos añadir este código a nuestro programa (para este ejemplo yo lo estoy poniendo en el constructor de un formulario)
public Main() { InitializeComponent(); Database.SetInitializer<DataContext>(new DropCreateDatabaseIfModelChanges<DataContext>()); using (DataContext context = new DataContext()) { Blog b = context.Blog.FirstOrDefault(); } }Bien este código tiene dos partes importantes
- En la primera parte indicaremos cual es la estrategia de incialización de nuestro modelo. Entity Framework Code First incluye 3 inicializadores (ojo con estos inicializadores cuando pasemos nuestra aplicación a producción porque podemos perder todos nuestros datos):
- CreateDatabaseIfNotExist
- DropCreateDatabaseAlways
- DropCreateDatabaseIfModelChanges
- En la segunda parte hacemos una simple consulta (obtenemos el primer blog) a nuestro contexto porque si no realizamso una consulta no se ejecutaría nuestro inicializador (si nunca accedemos a nuestros datos, para que se va a perder el tiempo en crear el modelo de datos).
Vemos que con el modelo conceptual (clases POCO) y la definición de las claves primarias Entity Framework ha creado un esquena de base de datos que se ajusta perfectamente a nuestra definición. Inlcluso a creado una tabla intermedia (TagPost) para poder gestionar la relación muchos a muchos que hay entre los Posts y los Tags.
A partir de aquí podemos modificar nuestro modelo de datos a través de Fluent Api añadiendo estas lineas al método OnModeloCreating. Por ejemplo:
Evitar que la clave primaria sea un identity en la tabla Categoria
modelBuilder.Entity<Category>() .Property(p => p.IdCategory) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);Forzar a que un campo sea obligatorio (NOT NULL) y tenga una longitud máxima de 50 caracteres
modelBuilder.Entity<Blog>().Property(p => p.Title).IsRequired(); modelBuilder.Entity<Blog>().Property(p => p.Title).HasMaxLength(50);Evitar que una propiedad de nuestro modelo conceptual esté en en la base de datos
modelBuilder.Entity<Post>().Ignore(p => p.HtmlTitle);Si volvemos a ejecutar nuestra aplicación y dado que nuestra estrategia de inicialización era borrar la base de datos si el modelo ha cambiado, y éste ha cambiado, veremos que que nuestros cambios se ha realizado de la forma esperada.
- El identificador de la tabla Category no es un identity
- Se han modificado la características del campo Title de la tabla Blog
- El campo HtmlTitle no se mapea en la tabla Post
Como vemos, tenemos total libertad para ir refinando nuestro modelo de datos a partir de nuestro modelo conceptual.
Happy coding !
Justo lo que necesitaba. Una guia tan buena como esta de este Framework ORM. Muchas gracias ;)
ResponderEliminarMe alegra que haya gustado.
Eliminar