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:

Все еще никакое разрешение. Интересное поведение обнаружило, хотя - нормальный SqlCommand бросит TimeoutException как ожидалось во время той же блокировки, которая делает SqlBulkCopy. Метод WriteToServer зависает неограниченно долго.

Вот подходы, которые мы попробовали - и которым не удалось - получить SqlBulkCopy. WriteToServer для последовательного броска тайм-аутов при ожидании:

  • МАРС (несколько активных наборов результатов) вкл\выкл
  • TableLock на по сравнению с прочь
  • Место назначения как таблица "кучи" по сравнению с индексированной таблицей
  • Более длинные/короче значения BulkTimeout (10 секунд к 5 минутам)
  • Внутренний по сравнению с внешней транзакцией

На данный момент, как обходное решение, я чередуюсь между a) помещением WriteToServer звонят в асинхронную обертку, таким образом, я могу время это сам и b) только вызовом WriteToServer однажды; после тайм-аутов ожидайте, пока обычный SqlCommand не успешно выполняется прежде, чем попробовать WriteToServer снова. Используя эти подходы, я, по крайней мере, могу остаться в управлении потока выполнения.

8
задан Paul Smith 16 February 2010 в 20:47
поделиться

2 ответа

Пробовали ли вы передать параметр SqlBulkOptions.TableLock в SqlBulkCopy? Эта опция (цитата) означает, что она:

Получит блокировку массового обновления на продолжительность операции массового копирования.

Таким образом, если есть другая обработка, блокирующая таблицу, это предотвратит получение блокировки и, теоретически, надежно приведет к тайм-ауту.

Обновление:
Я установил свою испытательную привязь и не могу воспроизвести. Чтобы заблокировать таблицу, я начал транзакцию в SSMS, выполнив SELECT * FROM TargetTable WITH (HOLDLOCK) . Я использовал тот же метод BulkCopy, который вы указали в вопросе, с использованием внутренних транзакций с таймаутом массовой загрузки 30 секунд. Каждая попытка массового копирования истекает, как и ожидалось, через 30 секунд. Затем он завершается успешно, когда я откатываю транзакцию SSMS.

Я использовал SQL Server 2008 Express, .NET 3.5.

Это не похоже на то, что после первой попытки тайм-аут массовой загрузки не передается правильно? т.е. он каким-то образом не установлен на "неопределенный".

Обновление 2:
Также включена поддержка нескольких активных наборов результатов в строке подключения, но каждый раз время ожидания постоянно истекает.

4
ответ дан 5 December 2019 в 23:15
поделиться

У меня была последняя проблема и для решения этой проблемы установите BulkCopyTimeout равным нулю.

bulkCopy.BulkCopyTimeout = 0;
1
ответ дан 5 December 2019 в 23:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: