# 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.&#x20;

{% hint style="info" %}
Se recomienda crear un índice por cada campo que es llave foránea para que las búsquedas sean mas rápidas
{% endhint %}

### Creación de Índice

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.

Creamos un índice para el campo CategoriaId, los índices que no son únicos empezaran con  **IX** seguido de la tabla (producto) seguido de la tabla con la cual tiene la llave foránea (categoria).

{% code title="ProductoConfiguration.cs" %}

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

{% endcode %}

### 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.&#x20;
* **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.

{% code title="ProductoConfiguration.cs" %}

```csharp
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);
     }
}
```

{% endcode %}

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

{% code title="CaducaContext.cs" %}

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

{% endcode %}

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

{% code title="CaducaContext.cs" %}

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

{% endcode %}

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
```
