索引鍵

索引鍵可作為每個實體實例的唯一識別碼。 EF 中的大部分實體都有單一索引鍵,其對應至關係資料庫中主鍵的概念(對於沒有索引鍵的 實體,請參閱 無索引鍵實體 )。 實體除了主鍵之外也可以有其他索引鍵(如需詳細資訊,請參閱 替代索引鍵 )。

設定主鍵

依照慣例,名為 Id<type name>Id 的屬性將會設定為實體的主鍵。

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

注意

擁有的實體類型 會使用不同的規則來定義索引鍵。

您可以將單一屬性設定為實體的主鍵,如下所示:

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

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

您也可以將多個屬性設定為實體的索引鍵, 這稱為複合索引鍵。 慣例只會在特定情況下設定複合索引鍵,例如擁有的類型集合。

注意

屬性 [PrimaryKey] 是在 EF Core 7.0 中引進的。 在舊版中使用 Fluent API。

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

產生值

針對非複合數值和 GUID 主鍵,EF Core 會依照慣例為您設定值產生。 例如,SQL Server 中的數值主鍵會自動設定為 IDENTITY 資料行。 如需詳細資訊,請參閱 有關特定繼承對應策略 之值產生 和 指引的檔。

主鍵名稱

依照慣例,在關係資料庫主鍵上會以名稱 PK_<type name> 建立。 您可以設定主鍵條件約束的名稱,如下所示:

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

索引鍵類型和值

雖然 EF Core 支援使用任何基本類型的屬性做為主鍵,包括 stringGuidbyte[] 和其他,並非所有資料庫都支援所有類型做為索引鍵。 在某些情況下,索引鍵值可以自動轉換成支援的型別,否則應該 手動 指定轉換。

將新的實體新增至內容時,索引鍵屬性必須一律具有非預設值,但某些類型將由 資料庫 產生。 在此情況下,EF 會在新增實體以供追蹤之用時嘗試產生暫存值。 在呼叫 SaveChanges 之後 ,暫存值將會由資料庫所產生的值取代。

重要

如果索引鍵屬性具有資料庫所產生的值,而且在加入實體時指定了非預設值,則 EF 會假設實體已存在於資料庫中,並且會嘗試更新它,而不是插入新的實體。 若要避免這種情況,請關閉產生值,或瞭解如何 指定所產生屬性 的明確值。

替代索引鍵

除了主鍵之外,替代索引鍵可作為每個實體實例的替代唯一識別碼;它可以做為關聯性的目標。 使用關係資料庫時,這會對應至替代索引鍵資料行上唯一索引/條件約束的概念,以及一或多個參考資料行的外鍵條件約束。

提示

如果您只想在資料行上強制執行唯一性,請定義唯一索引而不是替代索引鍵(請參閱 索引 )。 在 EF 中,替代索引鍵是唯讀的,並透過唯一索引提供額外的語意,因為它們可作為外鍵的目標。

替代金鑰通常會在需要時為您引進,您不需要手動設定它們。 根據慣例,當您識別不是主鍵作為關聯性目標的屬性時,會為您介紹替代索引鍵。

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

您也可以將單一屬性設定為替代索引鍵:

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_<type name>_<property name> (針對複合替代索引鍵 <property name> 會變成屬性名稱的底線分隔清單)。 您可以設定替代索引鍵索引和唯一條件約束的名稱:

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