では、あなたは本物のデバッガーだと思いますか? これを試してください:
私は Linq2Sql プロジェクトを持っていますが、突然、時折、一見ランダムに、同じ行の二重挿入が発生することを発見しました。
をサブクラス化DataContext
し、オーバーライドしSubmitChanges
ました。その中で、GetChangeSet()
の呼び出しの前後に を呼び出しbase.SubmitChanges()
、テキスト ファイル ロガーを使用してInserts
コレクション内のオブジェクトを記録しました。さらに、自動番号付けされた ID を記録するのに十分な時間、挿入されたオブジェクトへの参照を保持します。
MyTableA
二重挿入が発生すると、DB で、それぞれ 1 つの行がandに挿入される代わりに、それぞれMyTableB
2 つの行があることがわかります。SQL プロファイラーは、4 つの挿入ステートメントを 1 つずつすばやく連続して表示します。
insert into MyTableA(...
insert into MyTableB(...
insert into MyTableA(...
insert into MyTableB(...
Inserts
デバッグ ログを確認すると、コレクションには のとのの2つのオブジェクトしかありません。への呼び出し後、変更セットは空です (そうあるべきです)。また、自動付番 IDは、新しく挿入された行の大きい方の値を示します。MyClassA
MyClassB
base.SubmitChanges()
もう 1 つの有用な情報:デバッグ モードでステップ実行する場合、バグは発生しません。ブレークポイントなしで実行した場合のみ。これは、実行速度に関係していると思われます。
同じDataContext
サブクラスを 1 年以上使用していますが、この種の動作は製品で見たことがありません。と でのみ発生しMyClassA
ますMyClassB
。
要約する:
- デバッグ ログから、すべてが正しく機能しているように見えます。
- SQL プロファイラーでは、二重挿入が発生していることがわかります。
- この動作は、デバッグ モードでコードをステップ実行するときに発生しないことを除いて、前述の 2 つのクラスに対してのみ、頻繁に発生しますが、予測できません。
編集 - 新しい情報:サブクラス
内にDataContext
、次のコードがあります。
try {
base.SubmitChanges(ConflictMode.ContinueOnConflict);
} catch (ChangeConflictException) {
// Automerge database values for members that client has not modified.
foreach (ObjectChangeConflict occ in ChangeConflicts) {
occ.Resolve(RefreshMode.KeepChanges);
}
}
// Submit succeeds on second try.
base.SubmitChanges(ConflictMode.FailOnFirstConflict);
MyTableA
両方ともMyTableB
必須の外部キーOtherTableID
参照を持っていますOtherTable
。二重挿入ChangeConflictException
は、共通の親テーブルの更新中に発生すると発生しますOtherTable
。
私たちは今、香りに取り組んでいます...