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

Relación de muchos a muchos mediante Data Annotations:

Para lograr configurar una relación de muchos a muchos en Entity Framework Code First solo debemos agregar una propiedad de tipo colección en cada una de las entidades, obviamente dónde una referencia a la otra, entonces veamos cómo quedarán nuestras entidades Producto y Categoría:

    [Table("Productos")]
    public class Producto
    {
        public Producto()
        {
            Categorias = new HashSet<Categoria>();
        }
 
        [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; }
 
        public virtual ICollection<Categoria> Categorias { getset; }
    }

Cómo podemos ver agregamos la propiedad virtual de tipo ICollection Categoría, y en el constructor inicializamos dicha propiedad para evitar Null Reference Exception cuando agreguemos categorías al producto. Ahora hacemos lo mismo para la entidad Categoría:

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

Y listo ya con esto tenemos configurada nuestra relación de muchos a muchos entre las entidades Producto y Categoría, para probar vamos a crear una aplicación de consola y copiamos el siguiente código, obviamente con todo el contexto y demás que hemos creado en anteriores ejemplos:

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

Y ahora podemos ver que se han creado las tablas Productos y Categorías, y adicional se creó la tabla ProductoCategorias para representar la relación de muchos a muchos:

Relación de muchos a muchos mediante Fluent Api:


Ahora vamos a configurar la relación de muchos 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>().HasMany<Categoria>(c => c.Categorias).WithMany(e => e.Productos).Map(e =>
                e.MapLeftKey("IdProducto"));
 
            modelBuilder.Entity<Producto>().HasMany<Categoria>(c => c.Categorias).WithMany(e => e.Productos).Map(e =>
                e.MapRightKey("IdCategoria"));
 
            modelBuilder.Entity<Producto>().HasMany<Categoria>(c => c.Categorias).WithMany(e => e.Productos).Map(e =>
                e.ToTable("ProductosCategorias"));
 
            base.OnModelCreating(modelBuilder);
        }
    }

Por ultimo si borramos la base de datos anteriormente creada y volvemos a ejecutar el proyecto de consola, veremos que obtendremos los mismos resultados.

Y bueno amigos, eso es todo, espero les sea de utilidad y de interés este post acerca de relación de muchos a muchos en Entity Framework code First, en próximos artículos observaremos más acerca de inicializaciones y migraciones en Code First.

Este artículo también lo puedes encontrar en mi blog personal: http://www.eltavo.net/2014/03/entityframework-configurando-una.html

Saludos y buena suerte!