1. ホーム
  2. entity-framework

[解決済み] EF コード ナビゲーションプロパティを使用しない最初の外部キー

2022-09-20 18:31:39

質問

以下のようなエンティティがあるとします。

public class Parent
{
    public int Id { get; set; }
}
public class Child
{
    public int Id { get; set; }
    public int ParentId { get; set; }
}

Parentsテーブルへの外部キー制約でParentIdがデータベース内に作成されることを強制するための、コード最初の流暢なAPI構文は何ですか。 ナビゲーションプロパティを持つ必要なく ?

ナビゲーションプロパティのParentからChildを追加すれば、できることは知っています。

modelBuilder.Entity<Child>()
    .HasRequired<Parent>(c => c.Parent)
    .WithMany()
    .HasForeignKey(c => c.ParentId);

しかし、この特定のケースでは、ナビゲーション・プロパティは必要ありません。

どのように解決するのですか?

EF Code First Fluent APIでは、それは不可能です。データベースで外部キー制約を作成するために、常に少なくとも1つのナビゲーションプロパティが必要です。

Code First Migrations を使用している場合、パッケージマネージャーコンソールで新しいコードベースのマイグレーションを追加するオプションがあります ( add-migration SomeNewSchemaName ). モデルやマッピングに何か変更があった場合は、新しいマイグレーションが追加されます。何も変更していない場合、新しいマイグレーションを強制するために add-migration -IgnoreChanges SomeNewSchemaName . マイグレーションには空の UpDown というメソッドがあります。

次に Up メソッドに次のようなものを追加します。

public override void Up()
{
    // other stuff...

    AddForeignKey("ChildTableName", "ParentId", "ParentTableName", "Id",
        cascadeDelete: true); // or false
    CreateIndex("ChildTableName", "ParentId"); // if you want an index
}

このマイグレーションを実行する ( update-database を実行すると、次のような SQL 文が実行されます (SQL Server の場合)。

ALTER TABLE [ChildTableName] ADD CONSTRAINT [FK_SomeName]
FOREIGN KEY ([ParentId]) REFERENCES [ParentTableName] ([Id])

CREATE INDEX [IX_SomeName] ON [ChildTableName] ([ParentId])

あるいは、マイグレーションを使わずに、純粋な SQL コマンドとして

context.Database.ExecuteSqlCommand(sql);

ここで context は派生したコンテキストクラスのインスタンスであり sql は上記のSQLコマンドを文字列で表したものです。

このように、EFには ParentId が関係を記述する外部キーであることをEFは全く理解しません。EFはこれを通常のスカラプロパティとしてのみ扱います。どういうわけか、上記のすべては、SQL 管理ツールを開いて制約を手作業で追加することに比べて、より複雑で低速な方法に過ぎないのです。