Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
20
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

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

概要

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
20
Help us understand the problem. What are the problem?