Я пытаюсь найти разницу между использованием SqlBulkCopy с опцией копирования SqlBulkCopyOptions.UseInternalTransaction
и без нее, но в своем тестовом приложении я не обнаруживаю никакой разницы. Если BatchSize
, например, равно 0, и я добавляю 100 записей (в DataTable
), где запись номер 50 вызывает ошибку при добавлении ее в таблицу базы данных, я получаю 0 записей в таблице. Например, если для BatchSize
установлено значение 10, я получаю 40 записей (4 пакета по 10 записей, пятый пакет включает ошибочную запись и вызывает прерывание массового копирования). Неважно, установлен SqlBulkCopyOptions.UseInternalTransaction
или нет, я всегда получаю один и тот же результат. Похоже, что пакеты всегда копируются во внутренней транзакции.
Если вас заинтересовало мое тестовое приложение, вот оно: SqlBulkCopy-Error- and-Transaction-Test.zip
Мои вопросы:
- Является ли
SqlBulkCopyOptions.UseInternalTransaction
устаревшим, потому чтоSqlBulkCopy
всегда использует внутренние транзакции? - Если нет: каково фактическое значение этой опции? В каких случаях это будет иметь значение?
Надеюсь, кто-нибудь прояснит
Редактировать: Судя по ответу и комментариям, я предполагаю, что моя проблема недостаточно ясна. Я знаю документацию. В нем говорится, что «По умолчанию операция массового копирования является отдельной транзакцией». и что каждый пакет использует свою собственную транзакцию при передаче UseInternalTransaction
. Но если это означает, что по умолчанию операция массового копирования использует только одну транзакцию для всего массового копирования (а не по одной для каждого пакета), я не получил бы записи в базе данных, если бы я установил BatchSize на определенный размер и пакет, который лежит после первый вызывает ошибку. Если бы использовалась только одна транзакция, все записи, добавленные в журнал транзакций, были бы отброшены. Но я получаю записи партий, которые лежат перед партией, включающей ошибочную запись. В соответствии с этим кажется, что по умолчанию каждый пакет выполняется в своей собственной транзакции. Это означает, что не имеет значения, сдам ли я UseInternalTransaction
или нет. Если я на неправильном пути, я был бы очень признателен, если бы кто-нибудь мог уточнить.
Один факт может быть важен: я использую SQL Server 2012. Возможно, SQL Server 2008 ведет себя по-другому. Я проверю это.
Редактировать: Благодаря ответу от usr я думаю, что нашел ответ: я немного отладил и профилировал и обнаружил, что приватное поле _internalTransaction действительно не установлено, если UseInternalTransaction не определен. Затем SqlBulkCopy не использует собственную (внутреннюю) транзакцию. Но профилирование показало, что SqlBulkCopy использует TDS (Tabular Data Stream) для копирования данных (независимо от размера BatchSize). Я не нашел много информации о TDS, особенно для SQL Server, но я предполагаю, что SQL Server выполняет операции массового копирования TDS во внутренней транзакции. Поэтому UseInternalTransaction кажется избыточным для SQL Server, но на всякий случай я бы установил его.