【C#】SqlBulkCopy.WriteToServer不可靠地服從BulkCopyTimeout
我需要從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:
仍然沒有決心。不過,我們發現了一些有趣的行為——在使sqlbulkcopy.writetoserver方法無限期掛起的同一個鎖期間,普通的sqlcommand將按預期丟擲timeoutexception。
以下是我們嘗試過的一些方法,但這些方法都失敗了,無法使sqlbulkcopy.writetoserver在預期的情況下始終丟擲超時:
mars(多個活動結果集)開啟/關閉
桌鎖開啟與關閉
目標作為堆表與索引表
較長/較短的bulktimeout值(10秒到5分鐘)
內部與外部交易
目前,作為一種解決方法,我將交替使用以下兩種方法:a)將writetoserver呼叫放入非同步包裝器中以便自己計時;b)只調用writetoserver一次;超時後,等待常規sqlcommand成功,然後再嘗試writetoserver。使用這些方法,我至少能夠控制執行流。
解決辦法
是否嘗試將sqlbulkoptions.tablelock選項傳遞給sqlbulkcopy?該期權(報價)意味著它將:
獲取的批量更新鎖
批量複製操作的持續時間。
因此,如果有另一個程序鎖定表,它將防止獲得鎖,理論上,可靠地超時。
更新:
我自己設定了測試工具,無法複製。為了鎖定表,我在ssms中啟動了一個事務,執行SELECT * FROM TargetTable WITH (HOLDLOCK)。我使用了問題中包含的相同的bulkcopy方法,使用內部事務,批量載入超時為30秒。每次嘗試進行大容量複製都會在30秒後按預期超時。然後,當我回滾ssms事務時,它將成功。
我使用的是sqlserver2008express,.net 3.5。
這與第一次嘗試之後的情況不同,大容量載入超時沒有正確傳入?也就是說,它並沒有被設定為“無限期”。
更新2:
還打開了連線字串中的多個活動結果集支援,每次都會持續超時。