Entity Framework Core 2.2: Ejemplo de Modelado Maestro-Detalle – Facturas

En mi curso de Udemy de Entity Framework Core 2.1 me pidieron que haga un ejemplo de un modelado de una aplicación que maneje facturas. Vamos a hacer un ejemplo de esto. Solo que este ejemplo lo haremos con Entity Framework Core 2.2.

En esta entrada vamos a trabajar en la construcción de un ejemplo de un modelo Maestro-Detalle para un negocio que maneja facturas. Vamos a necesitar 3 entidades: Factura, DetalleFactura y Productos. A nivel conceptual, podemos ver esto como una tienda que emite facturas. Los clientes vienen, escogen una colección de productos, y los compran. El cliente va a recibir una factura, con un detalle de factura donde se indica cada producto comprado.

Las relaciones de nuestras entidades se dan de la siguiente manera:

  • Factura y DetalleFactura tienen una relación uno a muchos, donde a cada factura le corresponde un conjunto de detalles de factura.
  • DetalleFactura y Producto tienen una relación uno a uno.

Vamos a comenzar creando nuestros modelos:

public class Producto
{
   public int Id { get; set; }
   public string Nombre { get; set; }
   public string Descripcion { get; set; }
   public decimal Precio { get; set; }
}

public class FacturaDetalle
{
   public int Id { get; set; }
   [Required]
   public int FacturaId { get; set; }
   public Factura Factura { get; set; }
   [Required]
   public int ProductoId { get; set; }
   public Producto Producto { get; set; }
   [Required]
   public decimal Precio { get; set; }
   [Required]
   public int Cantidad { get; set; }
   public decimal Total { get; set; }
}

 public class Factura
{
   public int Id { get; set; }
   [Required]
   public DateTime FechaEmision { get; set; }
   public decimal Total { get; set; }
   public List<FacturaDetalle> Detalle { get; set; }
}

Todo esto que hicimos acá ya lo vimos en el curso ya mencionado.

Lo que podemos destacar es la repetición de la propiedad Precio en Producto y FacturaDetalle. La razón de hacer esto es porque entendemos que los precios de los productos pueden variar en el tiempo. Por eso nos vemos obligados a colocar el precio del producto en el detalle de la factura, aún cuando tengamos una relación con la tabla producto.

A continuación, veremos nuestra configuración del contexto de datos, que es un poco diferente en Entity Framework Core 2.2 a como era en Entity Framework Core 2.1:

public class ApplicationDbContext: DbContext
{
  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
   var productos = new List<Producto>()
   {
   new Producto(){Id=1, Nombre = "Lámpara", Descripcion = "Para iluminar tu vida", Precio = 40.99m},
   new Producto(){Id=2, Nombre = "Tableta Inteligente", Descripcion = "Para que sus hijos se críen solos", Precio = 180.99m}
   };

  modelBuilder.Entity<Producto>().HasData(productos);

  modelBuilder.Entity<FacturaDetalle>().Property(x => x.Total).HasComputedColumnSql("[Cantidad] * [Precio]");

  modelBuilder.Entity<Producto>().Property(x => x.Precio).HasColumnType("decimal(9,2)");
  modelBuilder.Entity<FacturaDetalle>().Property(x => x.Precio).HasColumnType("decimal(9,2)");
  modelBuilder.Entity<FacturaDetalle>().Property(x => x.Total).HasColumnType("decimal(12,2)");
  modelBuilder.Entity<Factura>().Property(x => x.Total).HasColumnType("decimal(16,2)");

  base.OnModelCreating(modelBuilder);
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
  optionsBuilder.UseSqlServer("Data Source=(localdb)\\mssqllocaldb;Initial Catalog=DemoFacturas;Integrated Security=True")
  // Esta opción solo debe ser usada en tiempo de desarrollo
  .EnableSensitiveDataLogging(true)
  .UseLoggerFactory(GetLoggerFactory());
}

  // El uso del Logger Factory es nuevo!
  private ILoggerFactory GetLoggerFactory()
  {
  IServiceCollection serviceCollection = new ServiceCollection();
  serviceCollection.AddLogging(builder =>
  builder.AddConsole()
  .AddFilter(DbLoggerCategory.Database.Command.Name,
  LogLevel.Information));
  return serviceCollection.BuildServiceProvider()
  .GetService<ILoggerFactory>();
}

  public DbSet<Factura> Facturas { get; set; }
  public DbSet<FacturaDetalle> FacturaDetalle { get; set; }
  public DbSet<Producto> Productos { get; set; }
}

Lo diferente en esta versión de Entity Framework Core, es el uso del ILoggerFactory para hacer un log de los queries ejecutados por EF Core.

Vamos a ver entonces cómo insertar una factura con su detalle en la base de datos:

static void CreandoLaFacturaYSuDetalleDeManeraSimultanea()
{
  using (var context = new ApplicationDbContext())
  {
    List<Producto> productos = context.Productos.ToList();

    var facturaDetalle1 = new FacturaDetalle();
    facturaDetalle1.ProductoId = productos[0].Id;
    facturaDetalle1.Precio = productos[0].Precio;
    facturaDetalle1.Cantidad = 3;

    var facturaDetalle2 = new FacturaDetalle();
    facturaDetalle2.ProductoId = productos[1].Id;
    facturaDetalle2.Precio = productos[1].Precio;
    facturaDetalle2.Cantidad = 1;

    List<FacturaDetalle> detalles = new List<FacturaDetalle>() { facturaDetalle1, facturaDetalle2 };

    var factura = new Factura();
    factura.FechaEmision = DateTime.Now;
    factura.Detalle = detalles;
    factura.Total = detalles.Sum(x => x.Precio * x.Cantidad);

    context.Add(factura);
    context.SaveChanges();
  }
}

Aquí vemos que lo hacemos es construir la factura con su detalle como un solo objeto, y luego insertamos la factura, la cual va a arrastrar su detalle hacia la base de datos. En el caso del campo Total de la factura, lo que hacemos es sumar el total de cada detalle de factura, multiplicando el precio por la cantidad.

Conclusión

Entity Framework Core 2.2 es la nueva versión de EF Core la cual nos trae ciertas mejoras. En esta entrada vimos que con nuestros conocimientos de EF Core 2.1, podemos desarrollar sin problemas con EF Core 2.2.

Si necesitas unas clases de EF Core 2.1, tenemos este curso para ti: https://www.udemy.com/introduccion-a-entity-framework-core-2-1-de-verdad/

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s