はじめに
現在利用しているアプリを新規アプリに変更するにあたって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();
}
}
}
分かってしまえばなんてことないことですが、分かるまでは「なんで?」と思って、他にいろいろと原因を探して、無駄な時間を費やしてしまいます。
同じように困っている人がいれば、参考となればと思います。