EntityFrameworkのSaveChanges()の挙動

ちょこっとプロジェクト進捗上迷走したのでTipsメモメモです。

よくあるアレ(仕様変更。というか運用イメージの変更)のため、単一性を求められるデータのトランザクション管理がうまくいかなくなった…

というか初期仕様時になんとなく「これで大丈夫やろうか・・・?」というのが残ってて、リリース間近に露呈するというなんとも苦い状況でのお話。

まあ、こういうusingブロックにて…

using (var context = new SampleContext())
{
   using (var tran = context.Database.BeginTransaction())
   {
     ①処理内容・・・・・
   ②context.SaveChanges();
   }
}

コンテキストを取得して、明示的にトランザクションを開始してます。

①処理内容が、既存のデータを検索して、その結果から次のデータに持たせる値を生成する、という流れで、

一連の処理をトランザクション内(テーブルロック)で処理する必要がありました。

もちろん、最後に②SaveChangesで更新しますが、そのときの挙動がうまくいかない。

というのも、キーとなるIDをトランザクション内で取得して加工(加算)して新規挿入データに使用する、というもの。

当初は単一のデータ登録を想定でしたが、一気に大量に登録する必要があり、

よーするにIDの整合性が成り立たなくなってしまった。(重複する!)

これは困った。

完全なテーブルロックをかけると、下手したら数分止まってしまう。

ID発行のメソッドは複雑なロジックで、ID最大値を取得して加工しなければならないです。

これがあるために整合性が保てない。

もー最初から採番テーブルとか用意したらええやんか!→あとの祭り。

結局一晩なやんだ挙句、採番テーブルとストアドプロシージャで実装変更することにしまして。

だがしかし!テーブルロックの挙動がおかしい??

①の中で、外部ファイルから食わせたデータを大量にループ処理→その都度IDを新規発行→②登録

なのですがその間ずーっとテーブルがロックされてて、なんじゃこりゃ?となってました。

結論をいうと、

BeginTransaction()

これ、いらないですよね。

ストアドプロシージャでセレクトロックをかけているので、

SaveChangesでトランザクション保護されてるやん…

って話でした。

 

もっとドキュメントを読みましょう!