Мне нужно сосчитать исключения из последовательного тайм-аута из 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 будет генерировать исключение TimeoutException, как и ожидалось, во время той же блокировки, которая заставляет метод SqlBulkCopy.WriteToServer зависать бесконечно.
Вот подходы, которые мы попробовали - и которые потерпели неудачу - чтобы SqlBulkCopy.WriteToServer последовательно выбрасывал тайм-ауты, когда ожидается:
- MARS (несколько активных наборов результатов) вкл / выкл
- TableLock включен или выключен
- Место назначения в виде таблицы кучи и индексированной таблицы
- Более длинные / короткие значения BulkTimeout (от 10 секунд до 5 минут)
- Внутренняя и внешняя транзакция
На данный момент, в качестве обходного пути, я чередую между: а) помещением вызова WriteToServer в асинхронную оболочку, чтобы я мог сам рассчитать время, и б) только вызовом WriteToServer только один раз; после истечения времени ожидания дождитесь, пока обычная команда SqlCommand завершится успешно , прежде чем снова пытаться выполнить WriteToServer. Используя эти подходы, я по крайней мере могу контролировать поток выполнения.