索引

索引是許多資料存放區之間的常見概念。 雖然其在資料存放區中的實作可能會有所不同,但它們會用來根據資料行 (或一組資料行進行查閱,) 更有效率。 如需良好索引使用方式的詳細資訊,請參閱效能檔中的 索引一節

您可以指定資料行的索引,如下所示:

[Index(nameof(Url))]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

注意

依照慣例,會在每個屬性中建立索引 (或) 做為外鍵的屬性集。

EF Core 只支援每個不同屬性集的一個索引。 如果您在已定義索引的屬性集上設定索引,請依照慣例或先前的組態,變更該索引的定義。 如果您想要進一步設定慣例所建立的索引,這會很有用。

複合式索引

索引也可以跨越多個資料行:

[Index(nameof(FirstName), nameof(LastName))]
public class Person
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

多個資料行上的 索引也稱為複合式索引,可加速查詢,以篩選索引的資料行,但也會加速只篩選索引所涵蓋 之第一個 資料行的查詢。 如需詳細資訊 ,請參閱效能檔

索引唯一性

根據預設,索引不是唯一的:允許多個資料列具有索引資料行集 () 相同的值。 您可以讓索引成為唯一的,如下所示:

[Index(nameof(Url), IsUnique = true)]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

嘗試插入多個具有相同索引資料行集值的實體,將會導致擲回例外狀況。

索引排序次序

注意

這項功能正在 EF Core 7.0 中引進。

在大部分的資料庫中,索引所涵蓋的每個資料行都可以是遞增或遞減。 對於僅涵蓋一個資料行的索引,這通常並不重要:資料庫可以視需要以反向順序周遊索引。 不過,對於複合式索引而言,排序對於良好效能而言可能很重要,而且可能表示查詢所使用索引之間的差異。 一般而言,索引資料行的排序次序應該對應至查詢子句中指定的 ORDER BY 排序次序。

索引排序次序預設為遞增。 您可以讓所有資料行具有遞減順序,如下所示:

[Index(nameof(Url), nameof(Rating), AllDescending = true)]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public int Rating { get; set; }
}

您也可以依資料行指定排序次序,如下所示:

[Index(nameof(Url), nameof(Rating), IsDescending = new[] { false, true })]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public int Rating { get; set; }
}

索引名稱

依照慣例,在關係資料庫中建立的索引會命名為 IX_<type name>_<property name> 。 針對複合式索引, <property name> 會變成屬性名稱的底線分隔清單。

您可以設定資料庫中建立的索引名稱:

[Index(nameof(Url), Name = "Index_Url")]
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

索引篩選

某些關係資料庫可讓您指定篩選或部分索引。 這可讓您只編制資料行值的子集索引,減少索引的大小,並改善效能和磁碟空間使用量。 如需SQL Server篩選索引的詳細資訊,請參閱檔

您可以使用 Fluent API 來指定索引的篩選,並提供為 SQL 運算式:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasIndex(b => b.Url)
        .HasFilter("[Url] IS NOT NULL");
}

使用SQL Server提供者 EF 時,會針對屬於唯一 'IS NOT NULL' 索引的所有可為 Null 資料行新增篩選。 若要覆寫此慣例,您可以提供 null 值。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasIndex(b => b.Url)
        .IsUnique()
        .HasFilter(null);
}

包含的資料行

某些關係資料庫可讓您設定一組包含在索引中的資料行,但不屬於其「索引鍵」。 當查詢中的所有資料行都包含在索引中做為索引鍵或非索引鍵資料行時,這可以大幅改善查詢效能,因為不需要存取資料表本身。 如需SQL Server內含資料行的詳細資訊,請參閱檔

在下列範例中,資料 Url 行是索引鍵的一部分,因此該資料行的任何查詢篩選都可以使用索引。 此外,只存取 和 PublishedOn 資料行的 Title 查詢不需要存取資料表,而且會更有效率地執行:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Post>()
        .HasIndex(p => p.Url)
        .IncludeProperties(
            p => new { p.Title, p.PublishedOn });
}

檢查條件約束

檢查條件約束是標準關聯式功能,可讓您定義必須保存資料表中所有資料列的條件;任何嘗試插入或修改違反條件約束的資料將會失敗。 檢查條件約束類似于非 Null 條件約束 (,該條件約束禁止資料行) 或唯一條件約束 (禁止重複) ,但允許定義任意 SQL 運算式。

您可以使用 Fluent API 在資料表上指定檢查條件約束,並提供為 SQL 運算式:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Product>()
        .ToTable(b => b.HasCheckConstraint("CK_Prices", "[Price] > [DiscountedPrice]"));
}

您可以在相同的資料表上定義多個檢查條件約束,每個資料表都有自己的名稱。

注意:您可以透過社群套件 EFCore.CheckConstraints來設定一些常見的檢查條件約束。