Keys

键充当每个实体实例的唯一标识符。A key serves as a unique identifier for each entity instance. EF 中的大多数实体都有一个键,此键映射到关系数据库中 主键 的概念 (对于没有键的实体,请参阅 无键实体) 。Most entities in EF have a single key, which maps to the concept of a primary key in relational databases (for entities without keys, see Keyless entities). 实体可以有超过主键的其他键 (参阅 备用键 以获取详细信息) 。Entities can have additional keys beyond the primary key (see Alternate Keys for more information).

按照约定,将名为 Id 或的属性 <type name>Id 配置为实体的主键。By convention, a property named Id or <type name>Id will be configured as the primary key of an entity.

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

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

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

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

备注

拥有的实体类型 使用不同的规则来定义密钥。Owned entity types use different rules to define keys.

可以将单个属性配置为实体的主键,如下所示:You can configure a single property to be the primary key of an entity as follows:

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

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

你还可以将多个属性配置为实体的键,这称为组合键。You can also configure multiple properties to be the key of an entity - this is known as a composite key. 复合密钥只能使用熟知的 API 进行配置;约定将永远不会设置组合键,你不能使用数据批注来配置它。Composite keys can only be configured using the Fluent API; conventions will never setup a composite key, and you can not use Data Annotations to configure one.

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

主键名称Primary key name

按照约定,使用名称创建关系数据库主键 PK_<type name>By convention, on relational databases primary keys are created with the name PK_<type name>. 可以按如下所示配置 primary key 约束的名称:You can configure the name of the primary key constraint as follows:

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

键类型和值Key types and values

虽然 EF Core 支持使用任何基元类型的属性作为主键(包括 stringGuid 和其他类型),但 byte[] 并不是所有数据库都支持将所有类型作为键。While EF Core supports using properties of any primitive type as the primary key, including string, Guid, byte[] and others, not all databases support all types as keys. 在某些情况下,可以自动将键值转换为支持的类型,否则应 手动指定转换。In some cases the key values can be converted to a supported type automatically, otherwise the conversion should be specified manually.

在将新实体添加到上下文时,键属性必须始终具有非默认值,但某些类型将 由数据库生成Key properties must always have a non-default value when adding a new entity to the context, but some types will be generated by the database. 在这种情况下,当添加实体进行跟踪时,EF 会尝试生成一个临时值。In that case EF will try to generate a temporary value when the entity is added for tracking purposes. 在调用 SaveChanges 后,临时值将替换为数据库生成的值。After SaveChanges is called the temporary value will be replaced by the value generated by the database.

重要

如果某个键属性的值由数据库生成,而在添加实体时指定了一个非默认值,则 EF 将假定该实体在数据库中已存在,并且将尝试对其进行更新而不是插入一个新的值。If a key property has its value generated by the database and a non-default value is specified when an entity is added, then EF will assume that the entity already exists in the database and will try to update it instead of inserting a new one. 若要避免这种情况,请禁用值生成或了解 如何为生成的属性指定显式值To avoid this turn off value generation or see how to specify explicit values for generated properties.

备用键Alternate Keys

除了主键外,备用键还可用作每个实体实例的替代唯一标识符;它可用作关系的目标。An alternate key serves as an alternate unique identifier for each entity instance in addition to the primary key; it can be used as the target of a relationship. 当使用关系数据库时,这将映射到) 的替代键 (列上的唯一索引/约束的概念,以及引用 () 的列的一个或多个 foreign key 约束。When using a relational database this maps to the concept of a unique index/constraint on the alternate key column(s) and one or more foreign key constraints that reference the column(s).

提示

如果只是想要在列上强制唯一性,请定义唯一索引而不是备用键 (参阅 索引) 。If you just want to enforce uniqueness on a column, define a unique index rather than an alternate key (see Indexes). 在 EF 中,备用键为只读,并在唯一索引之上提供附加语义,因为它们可用作外键的目标。In EF, alternate keys are read-only and provide additional semantics over unique indexes because they can be used as the target of a foreign key.

通常会在需要时为您引入备用密钥,而不需要手动配置。Alternate keys are typically introduced for you when needed and you do not need to manually configure them. 按照约定,当您标识的属性不是作为关系目标的主键时,将为您引入备用密钥。By convention, an alternate key is introduced for you when you identify a property which isn't the primary key as the target of a relationship.

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

你还可以将单个属性配置为备用密钥:You can also configure a single property to be an alternate key:

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

你还可以将多个属性配置为替代密钥, (称为复合备用键) :You can also configure multiple properties to be an alternate key (known as a composite alternate key):

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

最后,按照约定,为替代键引入的索引和约束将被命名为 AK_<type name>_<property name> (,以便复合备用键 <property name> 成为) 的属性名称列表。Finally, by convention, the index and constraint that are introduced for an alternate key will be named AK_<type name>_<property name> (for composite alternate keys <property name> becomes an underscore separated list of property names). 您可以配置备用密钥的 index 和 unique 约束的名称:You can configure the name of the alternate key's index and unique constraint:

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