LoginSignup
1
2

More than 3 years have passed since last update.

EntityFramewofk Coreで自動採番となっているテーブルで指定のIDを追加したい

Posted at

はじめに

現在利用しているアプリを新規アプリに変更するにあたってSQL Serverに新しくデータベースを作って、そこに元のデータをいれようと思っていました。
テーブルをコードファーストで作っていたのですが、これだと旧テーブルから新テーブルにデータを移行する際に、IDが変わってしまうという問題がありました。
そこで、いろいろと調べていると、SET IDENTITY_INSERT [table名] ON を行えばいいということが分かり実装してみました。

問題が起きました

Master_Staff(旧テーブル) ⇒ Main_User(新テーブル)
蛇足ですが、昨今の"Master"は使わないようにしようという流れにあわせて、新規アプリでテーブル名を変更することにしました。

    internal async Task InsertMainUserAsync(newDBContext dbContext, List<Master_Staff> MasterStaffs)
    {
        await Task.Run(() =>
        {
            foreach (var s in MasterStaffs)
            {
                dbContext.Main_Users.Add(new Main_User()
                {
                    Main_UserId = s.Master_StaffId,
                    UserName = s.StaffName,
                });
            }
            dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users ON");
            dbContext.SaveChanges();
            dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users OFF");
        }
    }

SqlException: IDENTITY_INSERT が OFF に設定されているときは、テーブル 'Main_Users' の ID 列に明示的な値を挿入できません。
というエラーが起きました。

解決

いろいろと調べると、Microsoft Documentに生成されるプロパティに明示的な値を設定するというページがありました
そこにあるSampleは以下の通り

using (var context = new EmployeeContext())
{
    context.Employees.Add(new Employee { EmployeeId = 100, Name = "John Doe" });
    context.Employees.Add(new Employee { EmployeeId = 101, Name = "Jane Doe" });

    context.Database.OpenConnection();
    try
    {
        context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Employees ON");
        context.SaveChanges();
        context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Employees OFF");
    }
    finally
    {
        context.Database.CloseConnection();
    }
}

どうやら、同じ接続内でSET IDENTITY_INSERTを行わないとエラーになるようでした。
ということで以下のようにコードを変更したらうまくいきました。

    internal async Task InsertMainUserAsync(newDBContext dbContext, List<Master_Staff> MasterStaffs)
    {
        await Task.Run(() =>
        {
            foreach (var s in MasterStaffs)
            {
                dbContext.Main_Users.Add(new Main_User()
                {
                    Main_UserId = s.Master_StaffId,
                    UserName = s.StaffName,
                });
            }

            //ExecuteSqlRawとSaveChangesの部分を以下のように変更しました。
            dbContext.Database.OpenConnection();
            try
            {
                dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users ON");
                dbContext.SaveChanges();
                dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users OFF");
            }
            finally
            {
                dbContext.Database.CloseConnection();
            }
        }
    }

分かってしまえばなんてことないことですが、分かるまでは「なんで?」と思って、他にいろいろと原因を探して、無駄な時間を費やしてしまいます。
同じように困っている人がいれば、参考となればと思います。

1
2
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
1
2