5.3 Crear llaves fóraneas e índices

Vamos a crear una llave foránea en nuestra tabla producto para la tabla categoria y nuestro índice.

Se recomienda crear un índice por cada campo que es llave foránea

Dentro de nuestra carpeta Models -> Entity Configurations agregamos una nueva clase ProductoConfiguration.cs

Heredamos de la clase IEntityTypeConfiguration e implementamos el constructor de esta clase.

Creación de Índice

Creamos un índice para el campo CategoríaId, para los índices que no son únicos, empezaran con la palabra IX seguido de la tabla en nuestro caso producto, seguido de la tabla con la cual tiene la llave foránea, categoria

ProductoConfiguration.cs
public class ProductoConfiguration
: IEntityTypeConfiguration<Producto>
{
public void Configure(EntityTypeBuilder<Producto> builder)
{
builder.HasIndex(e => e.CategoriaId)
.HasName("IX_ProductoCategoria");
}
}

Creación de llave foránea

Para las llaves foráneas se utiliza la opción HasOne donde pasamos como parámetro el tipo de nuestra tabla, en este caso Categoria, luego elegimos WithMany para indicar que una categoría puede tener muchos productos, por último elegimos la opción para el borrar, las cuales son las siguientes:

  • DeleteBehavior.Restrict: No se puede borrar una categoría si hay productos que tienen esa categoría.

  • DeleteBehavior.Cascade: Al borrar una categoria se borrarán automáticamente todos los productos de esa categoría.

Para nuestro caso elegimos Restrict para no permitir borrar una categoría con productos.

ProductoConfiguration.cs
public class ProductoConfiguration
: IEntityTypeConfiguration<Producto>
{
public void Configure(EntityTypeBuilder<Producto> builder)
{
builder.HasIndex(e => e.CategoriaId)
.HasName("IX_ProductoCategoria");
builder.HasOne(typeof(Categoria))
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
}
}

Si deseas que todas tus tablas tengan la regla Restrict, puedes agregar el siguiente código a tu clase DBContext.

CaducaContext.cs
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var relationship in modelBuilder.Model.GetEntityTypes()
.SelectMany(e => e.GetForeignKeys()))
{
relationship.DeleteBehavior = DeleteBehavior.Restrict;
}
}

Recorremos todas las llaves foráneas de nuestro modelo y especificamos que la regla para borrar será restringir.

Agregamos la configuración de nuestra tabla Producto a la clase CaducaContext

CaducaContext.cs
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new CategoriaConfiguration());
modelBuilder.ApplyConfiguration(new ProductoConfiguration());
}

Agregamos nuestra migración en la Consola del Administrador de Paquetes

Add-Migration LLave_Productos_Categoria
migrationBuilder.AddForeignKey(
name: "FK_Producto_Categoria",
table: "Producto",
column: "CategoriaId",
principalTable: "Categoria",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);

En nuestro archivo de migración cambiamos el nombre de nuestra llave foránea para que siga el mismo nombrado que el índice

Actualizamos nuestra base de datos agregando el comando:

Update-Database