建立和設定模型

EF Core 會使用中繼資料 模型 來描述應用程式的實體類型如何對應至基礎資料庫。 此模型是使用一組 慣例 來建置的 - 啟發學習法,以尋找常見的模式。 然後,您可以使用中的對應屬性(也稱為 資料批註 和/或呼叫 ModelBuilder 方法 (也稱為 Fluent API OnModelCreating 來自訂 模型,這兩者都會覆寫慣例所執行的組態。

大部分的組態都可以套用至以任何資料存放區為目標的模型。 提供者也可以啟用特定資料存放區特定的設定,也可以忽略不支援或不適用的設定。 如需提供者特定設定的檔,請參閱 資料庫提供者 一節。

提示

您可以在 GitHub 上檢視本文的 範例

使用 Fluent API 設定模型

您可以在衍生內容中覆寫 OnModelCreating 方法,並使用 Fluent API 來設定模型。 這是最強大的組態方法,讓您能夠指定組態而不修改實體類別。 Fluent API 組態具有最高的優先順序,且會覆寫慣例及資料註解。 系統會依呼叫方法的順序套用組態,如果發生任何衝突,最新的呼叫將會覆寫先前指定的組態。

using Microsoft.EntityFrameworkCore;

namespace EFModeling.EntityProperties.FluentAPI.Required;

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    #region Required
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .IsRequired();
    }
    #endregion
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

提示

若要將相同的組態套用至模型中的多個物件,請參閱 大量設定

群組設定

若要減少 OnModelCreating 方法的大小,實體類型的所有設定可以另行擷取至實作 IEntityTypeConfiguration<TEntity> 的類別。

public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
    public void Configure(EntityTypeBuilder<Blog> builder)
    {
        builder
            .Property(b => b.Url)
            .IsRequired();
    }
}

然後,只要從 OnModelCreating 叫用 Configure 方法即可。

new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());

套用元件中的所有組態

您可以套用在指定組件中實作 IEntityTypeConfiguration 的類型中所指定的所有設定。

modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);

注意

因為我們未定義設定的套用順序,建議只有在順序不重要時,才使用此方法。

EntityTypeConfigurationAttribute 實體類型上使用

而不是明確呼叫 ConfigureEntityTypeConfigurationAttribute 可以改為放在實體類型上,讓 EF Core 能夠尋找及使用適當的組態。 例如:

[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Isbn { get; set; }
}

這個屬性工作表示每當模型中包含實體類型時, Book EF Core 都會使用指定的 IEntityTypeConfiguration 實作。 實體類型會使用其中一個一般機制包含在模型中。 例如,藉由建立 DbSet<TEntity> 實體類型的 屬性:

public class BooksContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    //...

或者,在 中 OnModelCreating 註冊它:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Book>();
}

注意

EntityTypeConfigurationAttribute 不會在元件中自動探索類型。 實體類型必須先新增至模型,才能在該實體類型上探索屬性。

使用資料註解

您也可以將特定屬性(稱為 資料批註 )套用至您的類別和屬性。 資料註解會覆寫慣例,但會受到 Fluent API 組態覆寫。

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace EFModeling.EntityProperties.DataAnnotations.Annotations;

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
}

[Table("Blogs")]
public class Blog
{
    public int BlogId { get; set; }

    [Required]
    public string Url { get; set; }
}

內建慣例

EF Core 包含預設啟用的許多模型建置慣例。 您可以在實 IConvention 作 介面的類別清單中找到所有它們。 不過,該清單不包含協力廠商資料庫提供者和外掛程式所引進的慣例。

應用程式可以移除或取代上述任何慣例,以及針對 EF 現成無法辨識的模式套用組態的新 自訂慣例

提示

以下顯示的程式碼來自 ModelBuildingConventionsSample.cs

移除現有的慣例

有時候其中一個內建慣例可能不適合您的應用程式,在此情況下可以移除。

提示

如果您的模型未使用對應屬性(也稱為資料批註)進行設定,則可以安全地移除名稱結尾 AttributeConvention 的所有慣例,以加速模型建置。

範例:不要為外鍵資料行建立索引

建立外鍵 (FK) 資料行的索引通常很合理,因此有內建慣例: ForeignKeyIndexConvention 。 查看與 和 關聯性 Blog 之實體類型的模型 偵錯檢視 ,我們可以看到兩個 Post 索引已建立-一個用於 FK,另一個則用於 AuthorIdBlogId FK。 Author

  EntityType: Post
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      AuthorId (no field, int?) Shadow FK Index
      BlogId (no field, int) Shadow Required FK Index
    Navigations:
      Author (Author) ToPrincipal Author Inverse: Posts
      Blog (Blog) ToPrincipal Blog Inverse: Posts
    Keys:
      Id PK
    Foreign keys:
      Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
      Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade
    Indexes:
      AuthorId
      BlogId

不過,索引會有額外負荷,而且可能不一定適合為所有 FK 資料行建立它們。 若要達成此目的, ForeignKeyIndexConvention 可以在建置模型時移除 :

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}

現在查看模型的 Post 偵錯檢視,我們看到尚未建立 FK 上的索引:

  EntityType: Post
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      AuthorId (no field, int?) Shadow FK
      BlogId (no field, int) Shadow Required FK
    Navigations:
      Author (Author) ToPrincipal Author Inverse: Posts
      Blog (Blog) ToPrincipal Blog Inverse: Posts
    Keys:
      Id PK
    Foreign keys:
      Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
      Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade

如有需要,仍然可以針對外鍵資料行明確建立索引,使用 IndexAttribute 或 搭配 中的 OnModelCreating 組態。

偵錯檢視

您可以在 IDE 的偵錯工具中存取模型產生器偵錯檢視。 例如,使用 Visual Studio:

Accessing the model builder debug view from the Visual Studio debugger

它也可以直接從程式碼存取,例如將偵錯檢視傳送至主控台:

Console.WriteLine(context.Model.ToDebugString());

偵錯檢視有簡短表單和長表單。 長表單也包含所有批註,如果您需要檢視關聯式或提供者特定的中繼資料,可能會很有用。 您也可以從程式碼存取長檢視:

Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));