冲扬心法

笑声激发自强,发愤、图强、飞身向上

   :: 首页  ::  ::  ::  :: 管理

  键充当每个实体实例(对应数据库表中的一条记录)的唯一标识符。

  EF中大多数实体都要一个键,此键映射到关系型数据库中‘主键’的概念。

  实体还可以有超过主键的其他键——备用键。

 

  1、约定:默认将名为Id或名为<type name>Id的属性配置为实体的主键:

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

  2、可以将单个属性配置为实体的主键:

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

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

  3、还可以将多个属性配置为主键(联合主键,或者叫组合键)。组合键的关键是确认复合秘钥(下文中的new { 属性1,  属性2 }),只能使用Fluent API进行配置。不会默认配置组合键,且不能通过数据批注来配置:

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

主键名称

  约定:对于关系型数据库,使用属性名创建主键的名称为 PK_<type name>。当然,也可以通过Fluent API的方式自定义配置主键约束名:

modelBuilder.Entity<PostModel>().HasKey(c => new { c.Title, c.Content }).HasName("PrimaryKey_Title_Content");

键类型和值

  尽管EF Core 支持使用任何基元类型的属性作为主键(包括 string 、 Guid 、byte[]和其他类型),但并不是所有数据库都支持将所有类型作为键。 在某些情况下,可以自动将键值转换为支持的类型,否则应 手动指定转换。

  在DbContext中添加实体时,键属性必须没有默认值,但某些类型将由数据库生成。这种情况下,当对实体进行追踪时,EF会尝试生成一个临时值,在调用SaveChanges方法后,临时值将被替换为数据库生成的值。

  重要:如果某个键属性的值由数据库生成(比如SQL Server中的自增列IDENTITY属性),而在添加实体时指定了一个非默认值,则 EF 将假定该实体在数据库中已存在,并且将尝试对其进行更新而不是插入一个新的值。 若要避免这种情况,请禁用值生成或了解 如何为生成的属性指定显式值

备用键

  除了主键,备用键还可用作每个实体实例的唯一标识符的替代(备用)。它可以作为一种关系的目标。在使用关系数据库时,这将映射到备用键列上的唯一索引/约束和引用该列的一个或多个外键约束的概念。

  注意:如果只希望对列强制唯一性,则定义唯一索引而不是备用键(请参阅索引)。在EF中,备用键是只读的,并且在唯一索引上提供额外的语义,因为它们可以用作外键的目标。

  

  备用键通常在需要时为您引入,您不需要手动配置它们。按照惯例,当您将一个不是主键的属性标识为关系的目标时,将为您引入一个备用键:

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

  也可以配置一个属性作为一个备用键::

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

  您还可以将多个属性配置为备用键(称为复合备用键):

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

  最后,按照约定,为备用键引入的索引和约束将被命名为AK_<类型名>_<属性名>(对于复合备用键<属性名>将成为一个下划线分隔的属性名列表)。你可以配置备用键的索引和唯一约束的名称:

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

 

posted on 2020-12-16 00:17  风雨一肩挑  阅读(888)  评论(0编辑  收藏  举报