EntityFrameworkCore で SQL Server の IDENTITY プロパティを使うときの注意点

EntityFrameworkCoreのバージョンは v2.0.1。

例えば次のようなテーブルがあるとする。

create table Entry (
    Id bigint identity(1,1) not null,
    Title nvarchar(100) not null,
    Body nvarchar(max) null,

  constraint pk_Entry primary key clustered 
  (
      Id asc
  )
)

このテーブルにマッピングする C# のクラスはこんな感じ。

public class Entry
{
    public long Id { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
}

EntityFrameworkCore の Fluent API で、クラスとテーブルをマッピングする。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Entry>()
        .Property(e => e.Id)
        .UseSqlServerIdentityColumn();
    modelBuilder.Entity<Entry>()
        .Property(e => e.Title)
        .IsRequired();
    modelBuilder.Entity<Entry>()
        .Property(e => e.Body);
}

これでいいと思っていたけど、実際に動かしてみるとダメだった。 UPDATE 時に Id を更新しようとしてしまい、SqlException 発生。死亡。

Id を更新しないように設定してあげないといけなかった。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Entry>()
        .Property(e => e.Id)
        .UseSqlServerIdentityColumn()
        .Metadata.AfterSaveBehavior = PropertySaveBehavior.Ignore; // Id 列を更新しないようにする
    modelBuilder.Entity<Entry>()
        .Property(e => e.Title)
        .IsRequired();
    modelBuilder.Entity<Entry>()
        .Property(e => e.Body);
}

最初、ドキュメントを探しても解決方法を見つけることができず途方に暮れたが、 GitHub リポジトリに登録されているイシューを見つけることができた。 嵌ったときはイシューも見る。これ大事。