lunes, 24 de febrero de 2014

[EntityFramework] Configurando una relación de uno a muchos en Code First

En el artículo anterior vimos cómo configurar una relación de uno a uno en Code First usando Data Annotations y Fluent Api, en esta ocasión vamos a ver cómo configurar una relación de uno a muchos usando las mismas entidades de dominio Producto y Categoria.

Relación de uno a muchos mediante Data Annotations:

Nuestra entidad Producto será de la siguiente forma:

    [Table("Productos")]
    public class Producto
    {
        [Key]
        public int Codigo { getset; }
 
        [Required]
        [Column("Nombre", TypeName = "varchar", Order = 2)]
        public string Nombre { getset; }
 
        [MaxLength(100), MinLength(10)]
        public string Descripcion { getset; }
 
        [NotMapped]
        public string CodigoIso { getset; }
 
        [ForeignKey("Categoria")]
        public int IdCategoria { getset; }
 
        public virtual Categoria Categoria { getset; }
    }

Cómo ven agregamos IdCategoria y especificamos que se trata de la clave foránea con respecto a la entidad categoria, de igual forma agregamos la propiedad Categoria de tipo Categoria que representa la relación, y a continuación en nuestra entidad Categoria agregaremos una colección de tipo Producto para indicar que una categoría puede tener uno o muchos productos:

    public class Categoria
    {
        [Key]
        public int Id { getset; }
 
        [MaxLength(100)]
        public string Nombre { getset; }
 
        [MaxLength(200)]
        public string Descripcion { getset; }
 
        [Required]
        public virtual ICollection<Producto> Producto { getset; }
    }

Y con esto tenemos configurada nuestra relación de una a muchos entre Productos y Categorías a través de Data Annotations, ahora para probar la configuración podemos crear una app de consola y copiar el siguiente código en la clase program:

    class Program
    {
        static void Main(string[] args)
        {
            var categoria = new Categoria { Id = 1, Nombre = "Lacteos", Descripcion = "Productos lacteos" };
            var producto = new Producto { Codigo = 1, Nombre = "Leche", Descripcion = "Producto Lacteo", Categoria = categoria };
            var producto2 = new Producto { Codigo = 2, Nombre = "Queso", Descripcion = "Producto Lacteo", Categoria = categoria };
            using (var contexto = new Context())
            {
                contexto.Productos.Add(producto);
                contexto.Productos.Add(producto2);
                contexto.SaveChanges();
            }
        }
    }

Relación de uno a muchos mediante Fluent Api:

Ahora vamos a configurar la relación de uno a muchos entre Productos y Categorías, pero esta vez vamos a usar Fluent Api para lograrlo:

    public class Context : DbContext
    {
        public Context() : base("Productos")
        {
            
        }
 
        public DbSet<Producto> Productos { getset; }
 
        public DbSet<Categoria> Categorias { getset; }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // Aquí haremos nuestras configuraciones con Fluent API.
 
            modelBuilder.Configurations.Add(new ProductoMappings());
 
            modelBuilder.Entity<Producto>()
                .HasRequired<Categoria>(c => c.Categoria)
                .WithMany(c => c.Productos)
                .HasForeignKey(c => c.IdCategoria);
 
            base.OnModelCreating(modelBuilder);
        }
    }

Cómo vemos en el método OnModelCreating especificamos la relación a través de Fluent Api, dónde indicamos la relación partiendo la entidad Producto e indicamos el WithMany con Categoría.

Y bueno amigos, eso es todo, espero les sea de utilidad y de interés este post acerca de relación uno a muchos en Entity Framework code First, en el próximo artículo observaremos cómo configurar una relación de muchos a muchos, para terminar con el tema de relaciones y seguir con otros temas.

Saludos y buena suerte!

miércoles, 19 de febrero de 2014

[EntityFramework] Configurar una relación uno a uno en Code First

En artículos anteriores, vimos cómo configurar nuestras entidades de dominio a través de Data Annotations y a través de Fluent Api, ahora vamos a ver cómo configurar diferentes relaciones en la base de datos mediante estas dos alternativas, en primera instancia vamos a ver cómo configurar una relación de uno a uno entre las entidades Producto y Categoria.

Relación de uno a uno mediante Data Annotations:

Nuestra entidad Categoria será de la siguiente forma:

    public class Categoria
    {
        public int Id { getset; }
 
        [MaxLength(100)]
        public string Nombre { getset; }
 
        [MaxLength(200)]
        public string Descripcion { getset; }
 
        [Required]
        public virtual Producto Producto { getset; }
    }

Entonces para nuestro ejemplo supondremos que un producto solo puede tener una categoría, y para configurar la relación a través de Data Annotations hacemos lo siguiente:

    [Table("Productos")]
    public class Producto
    {
        [Key]
        public int Codigo { getset; }
 
        [Required]
        [Column("Nombre", TypeName = "varchar", Order = 2)]
        public string Nombre { getset; }
 
        [MaxLength(100), MinLength(10)]
        public string Descripcion { getset; }
 
        [NotMapped]
        public string CodigoIso { getset; }
 
        [ForeignKey("Categoria")]
        public int IdCategoria { getset; }
 
        public virtual Categoria Categoria { getset; }
    }

Como podemos ver en nuestra entidad Producto creamos una propiedad de tipo entero llamada IdCategoria, y la decoramos con el atributo ForeignKey el cual nos indica que esta propiedad nos servirá para relacionarla con otra entidad, y vemos que en su constructor especificamos la palabra "Categoria", que hace alusión a la propiedad virtual que nos sirve para configurar la relación con la entidad Categoria, de esta forma una vez se cree la base de datos se creara la relación de uno a uno.

Para probar esto podemos crear una aplicación de consola y escribir el siguiente código en la clase Program:

    class Program
    {
        static void Main(string[] args)
        {
            var categoria = new Categoria { Id = 1, Nombre = "Lacteos", Descripcion = "Productos lacteos" };
            var producto = new Producto { Codigo = 1, Nombre = "Leche", Descripcion = "Producto Lacteo", Categoria = categoria };
            using (var contexto = new Context())
            {
                contexto.Productos.Add(producto);
                contexto.SaveChanges();
            }
        }
    }

Y observaremos que tan sólo agregando el producto a la base de datos también se agregara la categoría correspondiente en su respectiva tabla y con sus relaciones correspondientes. Ahora vamos a ver como lo podemos hacer pero esta vez usando Fluent Api.

Relación de uno a uno mediante Fluent Api:

Para configurar la relación a través de Fluent Api, creamos una clase de configuración para la entidad Categoria o lo hacemos directamente en el contexto como vimos en el artículo Configurando nuestras entidades de dominio con Fluent Api:

    public class CategoriaMappings : EntityTypeConfiguration<Categoria>
    {
        public CategoriaMappings()
        {
            // Crear relación con la entidad Producto.
            this.HasRequired(c => c.Producto).WithRequiredPrincipal(e => e.Categoria);
        }
    }

Como vemos homologamos el código planteado anteriormente con Data Annotations, indicando que en la entidad categoría se requiere un producto y de igual forma en la entidad productos se requiere una categoría.

Y bueno amigos, eso es todo, espero les sea de utilidad y de interés este post acerca de relación uno a uno en Entity Framework code First, en próximos artículos observaremos cómo configurar otros tipos de relaciones.

Saludos y buena suerte!


domingo, 2 de febrero de 2014

[EntityFramework] Configurando nuestras entidades de dominio con Fluent API

Cómo apreciamos en nuestro artículo anterior Configurando nuestras entidades de dominio con Data Annotations logramos configurar nuestras entidades de dominio a través de Data Annotations, con esto logramos definir características particulares de entidades y propiedades a la hora de ser mapeadas para la creación de la base de datos, esta es una forma de hacerlo, pero no la única que nos brinda Entity Framework Code First. En este artículo vamos a ver cómo podemos hacer lo mismo pero esta vez usaremos Fluent API, que nos permite hacer este tipo de configuraciones de una forma centralizada, teniendo acceso a cada entidad que tengamos en nuestro contexto y usando métodos encadenados y expresiones lambda para realizar la configuración.

Ahora vamos a implementar la misma configuración del ejemplo anterior dónde usamos Data Annotations, con Fluent API para que podamos comparar más fácil cómo es el trabajo con cada una, y en base a esto tomar una elección personal de cuál usar.

Lo primero que debemos hacer para usar Fluent Api, es sobre escribir el método OnModelCreating de nuestro contexto, ya con esto al interior de este método podremos realizar las configuraciones sobre las entidades, tal y cómo se muestra a continuación:

    public class Context : DbContext
    {
        public Context() : base("Productos")
        {
            
        }
 
        public DbSet<Producto> Productos { getset; }
 
        public DbSet<Categoria> Categorias { getset; }
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // Aquí haremos nuestras configuraciones con Fluent API.
            base.OnModelCreating(modelBuilder);
        }
    }

Cómo vemos ahora el método OnModelCreating recibe el parámetro modelBuilder de tipo DbModelBuilder, es con esta clase que lograremos hacer todas las configuraciones que necesitamos, ahora sí vamos a ver como lograr dichas configuraciones, las cuales haremos sobre la entidad Producto, la cual usamos en nuestro ejemplo anterior de Data Annotations:

    [Table("Productos")]
    public class Producto
    {
        [Key]
        public int Codigo { getset; }
 
        [Required]
        [Column("Nombre", TypeName = "varchar", Order = 2)]
        public string Nombre { getset; }
 
        [MaxLength(100), MinLength(10)]
        public string Descripcion { getset; }
 
        [NotMapped]
        public string CodigoIso { getset; }
    }

Ahora homologaremos todo lo que hicimos con Data Annotations a través de Fluent Api, de la siguiente manera:

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // Aquí haremos nuestras configuraciones con Fluent API.
 
            // Especificar el nombre de una tabla.
            modelBuilder.Entity<Producto>().Map(m => m.ToTable("Productos"));
 
            // establecer una primary key.
            modelBuilder.Entity<Producto>().HasKey(c => c.Codigo);
 
            // Definir un campo como requerida.
            modelBuilder.Entity<Producto>().Property(c => c.Nombre).IsRequired();
 
            // Definir el nombre de un campo.
            modelBuilder.Entity<Producto>().Property(c => c.Nombre).HasColumnName("Nombre");
 
            // Definir el tipo de un campo.
            modelBuilder.Entity<Producto>().Property(c => c.Nombre).HasColumnType("varchar");
 
            // Definir el orden de un campo.
            modelBuilder.Entity<Producto>().Property(c => c.Nombre).HasColumnOrder(2);
 
            // Definir el máximo de caracteres permitidos para un campo.
            modelBuilder.Entity<Producto>().Property(c => c.Descripcion).HasMaxLength(100);
 
            // indicar que no se debe mapear una pripiedad a la base de datos.
            modelBuilder.Entity<Producto>().Ignore(c => c.CodigoIso);
 
            base.OnModelCreating(modelBuilder);
        }

Como podemos ver, hemos homologado las instrucciones de primary key, nombres, requerido y demás características a través de Fluent Api, con esto podríamos quitar los Data Annotations de nuestra entidad de dominio Producto, y una vez se inicialice la base de datos se tendrán en cuenta las configuraciones especificadas en el método OnModelCreating.

Para terminar con el artículo quisiera darles un tip, para el trabajo con Code First Fluent Api, de una forma más ordenada, ya que como vemos la codificación en el método OnModelCreating puede crecer bastante ya que allí va la configuración para cada entidad, por esto una buena práctica es separar en clases la configuración de cada entidad, con esto logramos un código más ordenado y más reutilizable, ahora veamos cómo hacerlo:

Para esto sólo debemos crear una clase que herede de EntityTypeConfiguration<T> y en el constructor de esta clase codificar las configuraciones tal y como lo hicimos en el método OnModelCreating, cómo se muestra a continuación:

    public class ProductoMappings : EntityTypeConfiguration<Producto>
    {
        public ProductoMappings()
        {
            // Especificar el nombre de una tabla.
            this.Map(m => m.ToTable("Productos"));
 
            // establecer una primary key.
            this.HasKey(c => c.Codigo);
 
            // Definir un campo como requerida.
            this.Property(c => c.Nombre).IsRequired();
 
            // Definir el nombre de un campo.
            this.Property(c => c.Nombre).HasColumnName("Nombre");
 
            // Definir el tipo de un campo.
            this.Property(c => c.Nombre).HasColumnType("varchar");
 
            // Definir el orden de un campo.
            this.Property(c => c.Nombre).HasColumnOrder(2);
 
            // Definir el máximo de caracteres permitidos para un campo.
            this.Property(c => c.Descripcion).HasMaxLength(100);
 
            // indicar que no se debe mapear una pripiedad a la base de datos.
            this.Ignore(c => c.CodigoIso);
        }
    }

Haríamos estos para cada entidad, y en el método OnModelCreating sólo agregaríamos la configuración que acabamos de crear, de la siguiente forma:

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            // Aquí haremos nuestras configuraciones con Fluent API.
 
            modelBuilder.Configurations.Add(new ProductoMappings());
 
            base.OnModelCreating(modelBuilder);
        }

Y para despedirme quisiera anotar que un método de configuración no excluye al otro, es decir podríamos usar configuración a través de Data Annotations y también a través de Fluent Api sin ningún problema. Y bueno eso es todo espero les sea de utilidad y de interés este tema de configuración de entidades de dominio a través de Entity Framework Code First Fluent Api.

Saludos y buena suerte!