Chaves

Uma chave serve como um identificador exclusivo para cada instância de entidade. A maioria das entidades no EF tem uma única chave, que mapeia para o conceito de uma chave primária em bancos de dados relacionais (para entidades sem chaves, consulte entidades sem chave). As entidades podem ter chaves adicionais além da chave primária (consulte Chaves Alternativas para obter mais informações).

Como configurar uma chave primária

Por convenção, uma propriedade nomeada Id ou <type name>Id será configurada como a chave primária de uma entidade.

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; }
}

Observação

Tipos de entidade de propriedade usam regras diferentes para definir chaves.

Você pode configurar uma única propriedade para ser a chave primária de uma entidade da seguinte maneira:

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

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

Você também pode configurar várias propriedades para ser a chave de uma entidade - isso é conhecido como uma chave composta. As convenções só configurarão uma chave composta em casos específicos, como para uma coleção de tipos de propriedade.

Observação

O atributo [PrimaryKey] foi introduzido no EF Core 7.0. Use a API fluente em versões mais antigas.

[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; }
}

Geração de valor

Para chaves primárias numéricas e GUID não compostas, o EF Core configura a geração de valor para você por convenção. Por exemplo, uma chave primária numérica no SQL Server é configurada automaticamente para ser uma coluna IDENTITY. Para obter mais informações, consulte a documentação sobre a geração de valor e as diretrizes para estratégias de mapeamento de herança específicas.

Nome da chave primária

Por convenção, as chaves primárias de bancos de dados relacionais são criadas com o nome PK_<type name>. Você pode configurar o nome da restrição de chave primária da seguinte maneira:

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

Tipos e valores de chave

Embora o EF Core dê suporte ao uso de propriedades de qualquer tipo primitivo como a chave primária, incluindo string, Guid, byte[] e outros, nem todos os bancos de dados dão suporte a todos os tipos como chaves. Em alguns casos, os valores de chave podem ser convertidos em um tipo com suporte automaticamente, caso contrário, a conversão deve ser especificada manualmente.

As propriedades de chave sempre devem ter um valor não padrão ao adicionar uma nova entidade ao contexto, mas alguns tipos serão gerados pelo banco de dados. Nesse caso, o EF tentará gerar um valor temporário quando a entidade for adicionada para fins de acompanhamento. Depois que SaveChanges for chamado, o valor temporário será substituído pelo valor gerado pelo banco de dados.

Importante

Se uma propriedade de chave tiver seu valor gerado pelo banco de dados e um valor não padrão for especificado quando uma entidade for adicionada, o EF assumirá que a entidade já existe no banco de dados e tentará atualizá-la em vez de inserir uma nova. Para evitar isso, desative a geração de valor ou consulte como especificar valores explícitos para propriedades geradas.

Chaves alternativas

Uma chave alternativa serve como um identificador exclusivo alternativo para cada instância de entidade, além da chave primária; ele pode ser usado como o destino de uma relação. Ao usar um banco de dados relacional, isso mapeia para o conceito de um índice/restrição exclusivo nas colunas de chave alternativa e uma ou mais restrições de chave estrangeira que referenciam as colunas.

Dica

Se você quiser apenas impor a exclusividade em uma coluna, defina um índice exclusivo em vez de uma chave alternativa (consulte Índices). No EF, as chaves alternativas são somente leitura e fornecem semântica adicional sobre índices exclusivos, pois podem ser usadas como destino de uma chave estrangeira.

As chaves alternativas normalmente são introduzidas para você quando necessário e você não precisa configurá-las manualmente. Por convenção, uma chave alternativa é introduzida para você quando você identifica uma propriedade que não é a chave primária como o destino de uma relação.

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; }
}

Você também pode configurar uma única propriedade para ser uma chave alternativa:

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

Você também pode configurar várias propriedades para ser uma chave alternativa (conhecida como uma chave alternativa composta):

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

Por fim, por convenção, o índice e a restrição introduzidos para uma chave alternativa serão nomeados como AK_<type name>_<property name> (porque as chaves alternativas compostas <property name> se tornam uma lista separada de sublinhados de nomes de propriedades). Você pode configurar o nome do índice da chave alternativa e a restrição exclusiva:

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