Creando una base de datos nueva con EF Core

.Net Core empieza a estar en auge y, con él, se está empezando a utilizar EF Core, por lo que la primera que pregunta que se nos plantea es ‘¿cómo puedo crear una base de datos en EF Core?’ En este post voy a explicar de forma básica cómo se haría, creando una pequeña base de datos, definiendo las claves primarias y relaciones entre las distintas tablas.
No entraré en detalles porque este post es básico y considero que puede ser objeteto de otro artículo entrar en detalles del modelado de la base de datos.
En este ejemplo voy a crear una aplicación de consola, pero el ejemplo es extensible a otro tipo de proyecto.

Añadir paquete nuget
Para trabajar con EF core es necesario añadir el paquete nuget que se muestra en la siguiente imagen

Crear entidades del modelo
Una vez instalado el paquete nuget, se procede a crear las entidades con las que se va a trabajar. En este ejemplo, se va a modelar una base de datos que tenga facturas (Orders). Cada factura tendrá un cliente (Customer) y podrá tener varios productos (Products). Para definir la relación muchos a muchos existe entre las facturas y los productos, se va a crear una entidad llamada Order2Product.
public class Order
{
public int Id { get; set; }
public string OrderNumber { get; set; }
public DateTime Date { get; set; }
public int CustomerId { get; set; }
public Customer Customer { get; set; }
public ICollection Order2Products { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string DocumentId { get; set; }
public ICollection Orders { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public ICollection Order2Products { get; set; }
}
public class Order2Product
{
public int OrderId { get; set; }
public int ProductId { get; set; }
public Product Product { get; set; }
public Order Order { get; set; }
}
Crear contexto
El siguiente paso es crear un contexto, heredando de DbContext. Este contexto tendrá en DbSet por cada una de las entidades que se acaban de crear. Asimismo, tiene que tener un constructor que reciba las opciones del contexto y las procese llamando al constructor del DbContext
public class Context : DbContext
{
public DbSet Customers { get; set; }
public DbSet Orders { get; set; }
public DbSet OrdersProducts { get; set; }
public DbSet Products { get; set; }
public Context(DbContextOptions options) : base(options) { }
public Context() { }
}
Configurar modelo
En este punto, se tiene un contexto con todas las entidades deseadas, por lo que ya se podría crear una base de datos, pero ésta no tendría ninguna relación entre las entidades y no se marcaría ningún campo como clave primaria, para ello, es necesario configurar las entidades.
Este ejemplo solo se va a centrar en dar un nombre a las tablas de la base de datos, crear una clave primaria por cada entidad y definir las relaciones entre éstas.
Por cada entidad, se ha creado una clase de configuración, con un único método estático que recibe y procesa un entityBuilder.
public class OrderConfig
{
public static void SetEntityBuilder(EntityTypeBuilder entityBuilder)
{
//The database table name is 'Orders'
entityBuilder.ToTable("Orders");
//Id property is the primary key and it´s required
entityBuilder.HasKey(x => x.Id);
entityBuilder.Property(x => x.Id).IsRequired();
//An order has one customer and many products
entityBuilder.HasOne(x => x.Customer).WithMany(x => x.Orders);
entityBuilder.HasMany(x => x.Order2Products).WithOne(x => x.Order);
}
}
public class CustomerConfig
{
public static void SetEntityBuilder(EntityTypeBuilder entityBuilder)
{
//The database table name is 'Customers'
entityBuilder.ToTable("Customers");
//Id property is the primary key and it´s required
entityBuilder.HasKey(x => x.Id);
entityBuilder.Property(x => x.Id).IsRequired();
//A customer has many orders
entityBuilder.HasMany(x => x.Orders).WithOne(x => x.Customer);
}
}
public class ProductConfig
{
public static void SetEntityBuilder(EntityTypeBuilder entityBuilder)
{
//The database table name is 'Products'
entityBuilder.ToTable("Products");
//Id property is the primary key and it´s required
entityBuilder.HasKey(x => x.Id);
entityBuilder.Property(x => x.Id).IsRequired();
//A product has many orders
entityBuilder.HasMany(x => x.Order2Products).WithOne(x => x.Product);
}
}
public class OrderProductsConfig
{
public static void SetEntityBuilder(EntityTypeBuilder entityBuilder)
{
//The database table name is 'Order2Product'
entityBuilder.ToTable("Order2Product");
//OrderId and ProductId are requiered and they´re the primary key
entityBuilder.HasKey(x => new { x.OrderId, x.ProductId });
entityBuilder.Property(x => x.OrderId).IsRequired();
entityBuilder.Property(x => x.ProductId).IsRequired();
//An order has many products and a product may be in many orders
entityBuilder.HasOne(x => x.Product).WithMany(x => x.Order2Products);
entityBuilder.HasOne(x => x.Order).WithMany(x => x.Order2Products);
}
}
Por resumir, aquí se indican las configuraciones realizadas:
- Asignar un nombre a la tabla: entityBuilder.ToTable(“TABLE_NAME”);
- Definir clave primaria: entityBuilder.HasKey(x => x.PRIMARY_KEY_PROPERTY);
- Definir un campo como requerido: entityBuilder.Property(x => x.PROPERTY).IsRequired();
- Relaciones entre tablas:
- entityBuilder.HasOne(x => x.PROPERTY).WithMany(x => x.PROPERTY);
- entityBuilder.HasMany(x => x.PROPERTY).WithOne(x => x.PROPERTY);
- entityBuilder.HasOne(x => x.PROPERTY).WithOne(x => x.PROPERTY);
Lo último que faltaría para tener la configuración definida completamente, sería establecer las configuraciones en el momento que se crea el modelo. Para ello, el contexto debe sobrescribir el método OnModelCreating(ModelBuilder modelBuilder) tal y como se muestra a continuación.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
CustomerConfig.SetEntityBuilder(modelBuilder.Entity());
OrderConfig.SetEntityBuilder(modelBuilder.Entity());
OrderProductsConfig.SetEntityBuilder(modelBuilder.Entity());
ProductConfig.SetEntityBuilder(modelBuilder.Entity());
base.OnModelCreating(modelBuilder);
}
Crear base de datos
Ya se han definido y configurado todas las entidades del modelo y se ha creado el contexto que las contiene. Solo falta crear una base de datos, contra la que trabajará EF Core para volcar toda la información en forma de tablas, relaciones, claves…
En este ejemplo, se ha creado una base de datos en un servidor SQL Server Express.


Tras crear la base de datos, se le indica al contexto la cadena de conexión de ésta. Para ello, basta con sobrescribir el método OnConfiguring e indicar la base de datos que se va a utilizar.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-96VBMK9\SQLEXPRESS;Initial Catalog=efExampleDb;Integrated Security=True");
}
Ahora, solo falta volcar la información del modelo a la base de datos. Esto se hace desde la consola del administrador de paquetes. Es posible que se tenga que instalar el siguiente paquete nuget (depende del tipo de proyecto con el que se esté trabajando)

Teniendo instalado el paquete, se abre la consola del administrador de paquetes y se realizan las siguientes acciones
- En el desplegable de proyecto predeterminado, seleccionar el proyecto que tenga el contexto
- Ejecutar el comando Add-Migration <Nombre de la migración> La primera migración, la que mete las primeras tablas en la base de datos, se suele llamar InitialMigration. Al lanzar este comando, se crean archivos con las migraciones en la carpera del proyecto Migrations.
- Ejecutar el comando Update-DataBase que actualiza la base de datos con los cambios del modelo.
Habiendo realizado estos pasos, si volvemos a la base de datos, se puede observar que se han creado todas las tablas, con los nombres, claves y relaciones especificadas.
Aquí os dejo un enlace en el que encontrar un proyecto de ejemplo con una implementación completa del ejemplo.
https://github.com/jorgediegocrespo/CreateEFCoreDB
Un saludo!!