共用方式為


建立和設定模型

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

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

小提示

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

使用 Fluent API 來設定模型

您可以在您衍生的 Context 中覆寫 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();
    }
}

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

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

每當模型中包含IEntityTypeConfiguration實體種類時,EF Core 都會使用指定的Book實作。 實體類型會使用其中一個一般機制包含在模型中。 例如,為實體類型創建一個 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。 查看與Post關聯的Blog實體類型模型Author,我們可以看到建立了兩個索引--一個用於BlogId FK,另一個則用於AuthorId FK。

  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:

從 Visual Studio 調試程式存取模型產生器偵錯檢視

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

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

偵錯視圖有短格式和長格式。 長表單也包含所有批注,如果您需要檢視關係型或提供者特定的元數據,可能會很有用。 您也可以從程式代碼存取長檢視:

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