ちょこっとプロジェクト進捗上迷走したのでTipsメモメモです。
よくあるアレ(仕様変更。というか運用イメージの変更)のため、単一性を求められるデータのトランザクション管理がうまくいかなくなった…
というか初期仕様時になんとなく「これで大丈夫やろうか・・・?」というのが残ってて、リリース間近に露呈するというなんとも苦い状況でのお話。
まあ、こういうusingブロックにて…
using (var context = new SampleContext())
{
using (var tran = context.Database.BeginTransaction())
{
①処理内容・・・・・
②context.SaveChanges();
}
}
コンテキストを取得して、明示的にトランザクションを開始してます。
①処理内容が、既存のデータを検索して、その結果から次のデータに持たせる値を生成する、という流れで、
一連の処理をトランザクション内(テーブルロック)で処理する必要がありました。
もちろん、最後に②SaveChangesで更新しますが、そのときの挙動がうまくいかない。
というのも、キーとなるIDをトランザクション内で取得して加工(加算)して新規挿入データに使用する、というもの。
当初は単一のデータ登録を想定でしたが、一気に大量に登録する必要があり、
よーするにIDの整合性が成り立たなくなってしまった。(重複する!)
これは困った。
完全なテーブルロックをかけると、下手したら数分止まってしまう。
ID発行のメソッドは複雑なロジックで、ID最大値を取得して加工しなければならないです。
これがあるために整合性が保てない。
もー最初から採番テーブルとか用意したらええやんか!→あとの祭り。
結局一晩なやんだ挙句、採番テーブルとストアドプロシージャで実装変更することにしまして。
だがしかし!テーブルロックの挙動がおかしい??
①の中で、外部ファイルから食わせたデータを大量にループ処理→その都度IDを新規発行→②登録
なのですがその間ずーっとテーブルがロックされてて、なんじゃこりゃ?となってました。
結論をいうと、
BeginTransaction()
これ、いらないですよね。
ストアドプロシージャでセレクトロックをかけているので、
SaveChangesでトランザクション保護されてるやん…
って話でした。
もっとドキュメントを読みましょう!