Contacts

    Entity Framework es un popular ORM (Object Relational Mapper), creado sobre ADO.Net (proveedor de datos de .Net). Es un ORM increíble, capaz de facilitar el trabajo del desarrollador, con muchas de sus funciones integradas.

    Una de las funciones populares de Entity Framework es el Fluent API, utiliza una interfaz fluida (encadenamiento de métodos) para anular las convenciones cuando se usa el enfoque Code First para modelar las entidades de su base de datos (esta anulación también se puede realizar a través de Data Annotations).

    El método OnModelCreating se encarga de encapsular estos cambios. Podemos usarlo así

    namespace Shop.Model
    {
        public class Product : BaseEntity
        {
            public int ProductID { get; set; }
            public string ProductName { get; set; }
            public decimal Price { get; set; }
            public Category Category { get; set; }
        }
    
        public class Category : BaseEntity
        {
            public int CategoryID { get; set; }
            public string CategoryName { get; set; }
            public ICollection<Product> Products { get; set; }
        }
    
        public class BaseEntity
        {
            public DateTime CreatedDate { get; set; }
            public DateTime EditedDate { get; set; }
        }
    }
    namespace Shop.Infrastructure.Context
    {
        public class ShopContext : DbContext
        {
            public ShopContext(DbContextOptions<ShopContext> options)
                : base(options) { }
    
            public DbSet<Product> Products { get; set; }
            public DbSet<Category> Categories { get; set; }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.Entity<Product>()
                    .HasKey(p => p.ProductID);
                modelBuilder.Entity<Product>()
                    .Property(p => p.ProductID)
                    .ValueGeneratedOnAdd();
                modelBuilder.Entity<Product>()
                    .Property(p => p.ProductName)
                    .IsRequired()
                    .HasColumnType("varchar")
                    .HasMaxLength(100);
                modelBuilder.Entity<Product>()
                    .Property(p => p.Price)
                    .HasColumnType("decimal(10,2)");
                modelBuilder.Entity<Product>()
                    .HasOne(p => p.Category)
                    .WithMany(c => c.Products)
                    .IsRequired();
                modelBuilder.Entity<Product>()
                    .Property(p => p.CreatedDate)
                    .HasColumnType("datetime2");
                modelBuilder.Entity<Product>()
                    .Property(p => p.EditedDate)
                    .HasColumnType("datetime2");
    
                modelBuilder.Entity<Category>()
                    .HasKey(c => c.CategoryID);
                modelBuilder.Entity<Category>()
                    .Property(c => c.CategoryName)
                    .IsRequired()
                    .HasColumnType("varchar")
                    .HasMaxLength(100);
                modelBuilder.Entity<Category>()
                    .Property(c => c.CreatedDate)
                    .HasColumnType("datetime2");
                modelBuilder.Entity<Category>()
                    .Property(c => c.CreatedDate)
                    .HasColumnType("datetime2");
            }
        }
    }

    Como puede ver, con solo dos pequeñas entidades, el método ya tiene más de veinte líneas. Siguiendo los conceptos de OOP y SOLID, debemos y podemos encapsular la responsabilidad a otra clase. Lo llamaremos Clases de configuración.

    En primer lugar, crearemos tres clases, para segregar la responsabilidad de cada configuración de modelo, ProducConfiguration, EntityBaseConfiguration y CategoryConfiguration.

    La clase EntityBaseConfiguration será la primera en construirse. Podemos implementar la interfaz IEntityTypeConfiguration<T>, implementará la configuración del método (si está utilizando EF 6, en lugar de EF core 6, puede llamar a EntityTypeConfiguration<T> en su lugar)

    namespace Shop.Context.Configration
    {
        public class BaseEntityConfiguration<TEntity> : IEntityTypeConfiguration<TEntity>
            where TEntity : BaseEntity
        {
            public virtual void Configure(EntityTypeBuilder<TEntity> builder)
            {
                throw new NotImplementedException();
            }
        }
    }

    Ahora llamamos a pasar todas nuestras configuraciones al método Configure (CreatedDate y EditedDate)

    public virtual void Configure(EntityTypeBuilder<TEntity> builder)
            {
                builder.Property(e => e.CreatedDate)
                    .IsRequired()
                    .HasColumnType("datetime2");
                builder.Property(e => e.EditedDate)
                    .IsRequired()
                    .HasColumnType("datetime2");
            }

    La categoría y la clase de producto se pueden implementar de la misma manera. Ambos heredarán de BaseEntityConfiguration, de esta manera, no tenemos que repetir la configuración para los campos CreatedDate y EditedDate, que había que repetir antes, dentro del método OnModelCreating.

    namespace Shop.Context.Configration
    {
        public class CategoryConfiguration : BaseEntityConfiguration<Category>, IEntityTypeConfiguration<Category>
        {
            public override void Configure(EntityTypeBuilder<Category> builder)
            {
                base.Configure(builder);
                builder.HasKey(c => c.CategoryID);
                builder.Property(c => c.CategoryName)
                    .IsRequired()
                    .HasColumnType("varchar")
                    .HasMaxLength(100);
                builder.Property(c => c.CreatedDate)
                    .HasColumnType("datetime2");
                builder.Property(c => c.CreatedDate)
                    .HasColumnType("datetime2");
            }
        }
    }
    namespace Shop.Context.Configration
    {
        public class ProductConfigurarion : BaseEntityConfiguration<Product>, IEntityTypeConfiguration<Product>
        {
            public override void Configure(EntityTypeBuilder<Product> builder)
            {
                base.Configure(builder);
                builder.HasKey(p => p.ProductID);
                builder.Property(p => p.ProductID)
                    .ValueGeneratedOnAdd();
                builder.Property(p => p.ProductName)
                    .IsRequired()
                    .HasColumnType("varchar")
                    .HasMaxLength(100);
                builder.Property(p => p.Price)
                    .HasColumnType("decimal(10,2)");
                builder.HasOne(p => p.Category)
                    .WithMany(c => c.Products)
                    .IsRequired();
                builder.Property(p => p.CreatedDate)
                    .HasColumnType("datetime2");
                builder.Property(p => p.EditedDate)
                    .HasColumnType("datetime2");
            }
        }
    }

    Ahora podemos volver a la clase Context, eliminar la configuración y llamar a nuestras nuevas clases de configuración creadas.

    public class ShopContext : DbContext
        {
            public ShopContext(DbContextOptions<ShopContext> options)
                : base(options) { }
    
            public DbSet<Product> Products { get; set; }
            public DbSet<Category> Categories { get; set; }
    
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.ApplyConfiguration(new ProductConfigurarion());
                modelBuilder.ApplyConfiguration(new CategoryConfiguration());
            }
        }

    Escribe tu Respuesta o Comentario

    Su dirección de correo no se hará público. Los campos requeridos están marcados *