LoginSignup
28
23

More than 5 years have passed since last update.

[EntityFrameworkCore]CodeFirstでテーブルに複合主キーを付ける

Last updated at Posted at 2017-08-31

概要

EntityFrameworkCore下でCodeFirstを使ってテーブルに複合主キーを設定する方法がEntityFramework6下での作法から変わったようなので(今更ですが)正しいやり方を調査しました。

環境

  • Microsoft.EntityFrameworkCore.Design(2.0.0)
  • Microsoft.NETCore.Platforms(1.1.0)
  • Visual Studio Community 2017 (15.3.3)

取り組んだこと

下記のようにEntityFramework6の頃の感覚でKeyとColumnのアノテーションで複合主キーの制約を付けたテーブルを書き、

FooModel.cs(before)
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class FooModel
{
        [Key]
        [Column(Order = 1)]
        public int Hage { get; set; }
        [Key]
        [Column(Order = 2)]
        public int Foo { get; set; }
        public DateTime LastModified { get; set; }
}

DBContextにプロパティ追加してEntityFrameworkCoreを使ったプロジェクトでAdd-Migrationしたところ

パッケージマネージャコンソール
PM> Add-Migration AddFooModel
System.InvalidOperationException: Entity type 'FooModel' has composite primary key defined with data annotations. To set composite primary key, use fluent API.
(中略)
Entity type 'FooModel' has composite primary key defined with data annotations. To set composite primary key, use fluent API.

「複合キーを設定する場合はfluentAPIを使ってください。」とのエラーメッセージが出ました。主キーが1つだけの場合はKeyによる指定もOKぽいですが、複合主キーを設定する場合には使えないようです。残念。

ということで今回使えないアノテーションをすべて外し、DBContext側にfluentAPIで複合主キーの制約を書きます。このとき、制約はDBContext.OnModelCreatingをオーバーライドして書き込みます。

FooModel.cs(after)
using System;
public class FooModel
{
        public int Hage { get; set; }
        public int Foo { get; set; }
        public DateTime LastModified { get; set; }
}
SampleContext.cs
using Microsoft.EntityFrameworkCore;
public class SampleContext : DbContext
{
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<FooModel>()
                .HasKey(c => new { c.Hage, c.Foo });
        }
}

これで再度Add-Migrationすると...

パッケージマネージャコンソール
PM> Add-Migration AddFooModel
To undo this action, use Remove-Migration.

うまく行ったみたいですね!一応Migrationファイルも確認してみます。

AddFooModel
    public partial class AddFooModel : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "FooModel",
                columns: table => new
                {
                    Hage = table.Column<int>(type: "int", nullable: false),
                    Foo = table.Column<int>(type: "int", nullable: false),
                    LastModified = table.Column<DateTime>(type: "datetime2", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_FooModel", x => new { x.Hage, x.Foo });
                });
        }
}

ちゃんと制約として複合主キーが設定されているようです。よしよし。

まとめ

  • EntityFramework6でも使っていた[Key][Column(Order=~)]のアノテーションで複合主キーをつけるやり方は終わったようです。
  • EntityFrameworkCoreでテーブルの複合主キーを実現する場合は DBContextのOnModelCreatingメソッドにてHasKeyメソッドで制約をつける。

参考URL

28
23
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
23