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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://abi.gitbook.io/net-core/5.-agregando-el-servicio-para-los-productos/5.3-crear-llaves-foraneas-e-indices.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
