EF Core では、メタデータ モデル を使用して、アプリケーションのエンティティ型が基になるデータベースにどのようにマップされるかを記述します。 このモデルは、一連の 規則 (一般的なパターンを探すヒューリスティック) を使用して構築されています。 その後、マッピング属性 (データ注釈とも呼ばれます) やModelBuilderの メソッド 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();
}
}
次に、Configure
からOnModelCreating
メソッドを呼び出します。
new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());
アセンブリ内のすべての構成の適用
特定のアセンブリに IEntityTypeConfiguration
を実装する型で指定されたすべての構成を適用できます。
modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);
注
構成が適用される順序は未定義であるため、このメソッドは順序が重要でない場合にのみ使用する必要があります。
エンティティ型での EntityTypeConfigurationAttribute
の使用
Configure
を明示的に呼び出す代わりに、EF Core が適切な構成を見つけて使用できるように、EntityTypeConfigurationAttributeをエンティティ型に配置できます。 例えば次が挙げられます。
[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から取得されています。
既存の規則の削除
組み込みの規則の 1 つがアプリケーションに適していない場合があり、その場合は削除できます。
ヒント
モデルで構成にマッピング属性 (データ注釈とも呼ばれます) が使用されていない場合は、名前が AttributeConvention
で終わるすべての規則を安全に削除して、モデルの構築を高速化できます。
例: 外部キー列のインデックスを作成しない
通常、外部キー (FK) 列のインデックスを作成するのが理にかなっています。そのため、これには組み込みの規則があります: ForeignKeyIndexConvention。
とPost
とのリレーションシップを持つBlog
エンティティ型のモデル Author
を見ると、BlogId
FK 用と AuthorId
FK 用の 2 つのインデックスが作成されていることがわかります。
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 では次のようになります。
また、コードから直接アクセスすることもできます。たとえば、デバッグ ビューをコンソールに送信します。
Console.WriteLine(context.Model.ToDebugString());
デバッグ ビューには、短い形式と長い形式があります。 長い形式にはすべての注釈も含まれています。これは、リレーショナルまたはプロバイダー固有のメタデータを表示する必要がある場合に便利です。 長いビューには、コードからもアクセスできます。
Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));
.NET