Chiavi

Una chiave funge da identificatore univoco per ogni istanza di entità. La maggior parte delle entità in Entity Framework ha una singola chiave, che è mappata al concetto di chiave primaria nei database relazionali (per le entità senza chiavi, vedere Entità senza chiave). Le entità possono avere chiavi aggiuntive oltre la chiave primaria . Per altre informazioni, vedere Chiavi alternative.

Configurazione di una chiave primaria

Per convenzione, una proprietà denominata Id o <type name>Id verrà configurata come chiave primaria di un'entità.

internal class Car
{
    public string Id { get; set; }

    public string Make { get; set; }
    public string Model { get; set; }
}

internal class Truck
{
    public string TruckId { get; set; }

    public string Make { get; set; }
    public string Model { get; set; }
}

Nota

I tipi di entità di proprietà usano regole diverse per definire le chiavi.

È possibile configurare una singola proprietà come chiave primaria di un'entità come indicato di seguito:

internal class Car
{
    [Key]
    public string LicensePlate { get; set; }

    public string Make { get; set; }
    public string Model { get; set; }
}

È anche possibile configurare più proprietà come chiave di un'entità, nota come chiave composita. Le convenzioni configurano solo una chiave composita in casi specifici, ad esempio per una raccolta di tipi di proprietà.

Nota

L'attributo [PrimaryKey] è stato introdotto in EF Core 7.0. Usare l'API Fluent nelle versioni precedenti.

[PrimaryKey(nameof(State), nameof(LicensePlate))]
internal class Car
{
    public string State { get; set; }
    public string LicensePlate { get; set; }

    public string Make { get; set; }
    public string Model { get; set; }
}

Generazione di valore

Per le chiavi primarie numeriche e GUID non composite, EF Core configura la generazione di valori per convenzione. Ad esempio, una chiave primaria numerica in SQL Server viene configurata automaticamente come colonna IDENTITY. Per altre informazioni, vedere la documentazione sulla generazione di valori e indicazioni per strategie di mapping di ereditarietà specifiche.

Nome chiave primaria

Per convenzione, nei database relazionali vengono create chiavi primarie con il nome PK_<type name>. È possibile configurare il nome del vincolo di chiave primaria nel modo seguente:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasKey(b => b.BlogId)
        .HasName("PrimaryKey_BlogId");
}

Tipi e valori di chiave

Anche se EF Core supporta l'uso di proprietà di qualsiasi tipo primitivo come chiave primaria, tra cui string, Guidbyte[] e altri, non tutti i database supportano tutti i tipi come chiavi. In alcuni casi i valori chiave possono essere convertiti automaticamente in un tipo supportato, altrimenti la conversione deve essere specificata manualmente.

Le proprietà chiave devono avere sempre un valore non predefinito quando si aggiunge una nuova entità al contesto, ma alcuni tipi verranno generati dal database. In tal caso EF tenterà di generare un valore temporaneo quando l'entità viene aggiunta a scopo di rilevamento. Dopo che SaveChanges viene chiamato il valore temporaneo verrà sostituito dal valore generato dal database.

Importante

Se il valore di una proprietà chiave è generato dal database e viene specificato un valore non predefinito quando viene aggiunta un'entità, EF presuppone che l'entità esista già nel database e tenterà di aggiornarla invece di inserirla una nuova. Per evitare questo problema, disattivare la generazione di valori o vedere come specificare valori espliciti per le proprietà generate.

Chiavi alternative

Una chiave alternativa funge da identificatore univoco alternativo per ogni istanza di entità oltre alla chiave primaria; può essere usato come destinazione di una relazione. Quando si usa un database relazionale, questo esegue il mapping al concetto di indice/vincolo univoco nelle colonne chiave alternative e uno o più vincoli di chiave esterna che fanno riferimento alle colonne.

Suggerimento

Se si vuole applicare solo l'univocità su una colonna, definire un indice univoco anziché una chiave alternativa (vedere Indici). In Entity Framework le chiavi alternative sono di sola lettura e forniscono semantiche aggiuntive su indici univoci perché possono essere usate come destinazione di una chiave esterna.

Le chiavi alternative vengono in genere introdotte quando necessario e non è necessario configurarle manualmente. Per convenzione, viene introdotta una chiave alternativa quando si identifica una proprietà che non è la chiave primaria come destinazione di una relazione.

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Post>()
            .HasOne(p => p.Blog)
            .WithMany(b => b.Posts)
            .HasForeignKey(p => p.BlogUrl)
            .HasPrincipalKey(b => b.Url);
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public string BlogUrl { get; set; }
    public Blog Blog { get; set; }
}

È anche possibile configurare una singola proprietà come chiave alternativa:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Car>()
        .HasAlternateKey(c => c.LicensePlate);
}

È anche possibile configurare più proprietà come chiave alternativa (nota come chiave alternativa composita):

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Car>()
        .HasAlternateKey(c => new { c.State, c.LicensePlate });
}

Infine, per convenzione, l'indice e il vincolo introdotti per una chiave alternativa verranno denominati AK_<type name>_<property name> (per le chiavi <property name> alternative composite diventa un elenco di nomi di proprietà separati da caratteri di sottolineatura). È possibile configurare il nome dell'indice e del vincolo univoco della chiave alternativa:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Car>()
        .HasAlternateKey(c => c.LicensePlate)
        .HasName("AlternateKey_LicensePlate");
}