SqlBulkCopyからのシーケンシャルタイムアウト例外をカウントする必要があります。これをテストするために、外部アプリを使用してトランザクションを開始し、ターゲットテーブルをロックします。
SqlBulkCopyは、最初の呼び出しでのみ、予期したときにタイムアウト例外をスローします。外部接続とトランザクション、および接続文字列と内部トランザクションを使用してみました。外部接続とトランザクションでは、接続を開いたり、トランザクションを開始またはコミットしたりするのに無限の待機が発生することはありませんでしたが、常にで待機していました.WriteToServer()
。
制限SqlBulkCopy.WriteToServer()
に達したときにタイムアウト例外を確実にスローする、これに対するいくつかのアプローチはありますか?.BulkCopyTimeout
public void BulkCopy(string connectionString, DataTable table, int bulkTimeout)
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
connectionString,
SqlBulkCopyOptions.UseInternalTransaction))
{
bulkCopy.BulkCopyTimeout = bulkTimeout;//e.g. 120 sec.
//... fill with data, map columns...
bulkCopy.WriteToServer(table);
// ^^^^ waits indefinitely, doesn't throw until *after*
// the lock is released.
}
}
ブロックのスコープ内で例外を処理するのではなく、例外をバブルアップさせる方using
が好きですが、いつでも再スローできます。洞察に感謝します。
アップデート1:
まだ解決策はありません。ただし、興味深い動作が発見されました。通常のSqlCommandは、SqlBulkCopy.WriteToServerメソッドが無期限にハングするのと同じロック中に、期待どおりにTimeoutExceptionをスローします。
SqlBulkCopy.WriteToServerが予期したときに一貫してタイムアウトをスローするようにするために、私たちが試した(そして失敗した)アプローチは次のとおりです。
- MARS(複数のアクティブな結果セット)のオン/オフ
- TableLockのオンとオフ
- ヒープテーブルとインデックステーブルとしての宛先
- より長い/より短いBulkTimeout値(10秒から5分)
- 内部トランザクションと外部トランザクション
今のところ、回避策として、a)WriteToServer呼び出しを非同期ラッパーに入れて、自分で時間を計ることができるようにすることと、b)WriteToServerを1回だけ呼び出すことを交互に行っています。タイムアウト後、通常のSqlCommandが成功するまで待ってから、 WriteToServerを再試行してください。これらのアプローチを使用することで、少なくとも実行フローの制御を維持することができます。