2014-10-27 4 views
12

Я вставки данных через SqlBulkCopy так:SqlBulkCopy автоматически запускает транзакцию?

public void testBulkInsert(string connection, string table, DataTable dt) 
{ 
    using (SqlConnection con = new SqlConnection(connection)) 
    { 
     con.Open(); 

     using (SqlBulkCopy bulkCopy = new SqlBulkCopy(con)) 
     { 
      bulkCopy.DestinationTableName = table; 
      bulkCopy.WriteToServer(dt); 
     } 
    } 
} 

Будет ли это автоматически завернутые в транзакции SQL, так что если что-то пойдет не так на полпути через БД будет оставаться в том же состоянии, как это было до того, как Началась навальная вставка? Или будет введена половина данных?

т.е. является необходимым для меня явно вызвать con.BeginTransaction

Или, если я называю конструктор SqlBulkCopy «s, которая принимает строку, является то, что лучший способ получить это произойдет в сделке?

public void testBulkInsert(string connection, string table, DataTable dt) 
{ 
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) 
    { 
     bulkCopy.DestinationTableName = table; 
     bulkCopy.WriteToServer(dt); 
    } 
} 

Я считаю docs немного неясным по этому вопросу, так как они изначально заявляют, что

По умолчанию основной операции копирования выполняются в изолированном операции. Операция массового копирования происходит в не-транзакционной образом, без возможности для прокатки его обратно

, но потом состояние

По умолчанию основная часть операции копирования его собственной транзакции. Когда вы хотите выполнить выделенную операцию массовой копии, создайте новый экземпляр из SqlBulkCopy со строкой подключения или используйте существующий объект SqlConnection без активной транзакции. В каждом сценарии операция массового копирования создает, а затем совершает или откатывает транзакцию .

Так это надо делать:

public void testBulkInsert(string connection, string table, DataTable dt) 
{ 
    using (SqlConnection con = new SqlConnection(connection)) 
    { 
     con.Open(); 
     using (SqlTransaction tr = con.BeginTransaction(IsolationLevel.Serializable)) 
     { 
      using (SqlBulkCopy bulkCopy = new SqlBulkCopy(con, SqlBulkCopyOptions.Default, tr)) 
      { 
       bulkCopy.DestinationTableName = table; 
       bulkCopy.WriteToServer(dt); 
      } 
      tr.Commit(); 
     } 
    } 
} 
+0

Почему вы не пробовали? И какая часть документации заставила вас думать, что это будет так? – TomTom

+1

Эта часть: * По умолчанию операция массового копирования - это его собственная транзакция *, но затем она также говорит. * Операция массовой копии выполняется не трансактным способом, без возможности ее возврата *, поэтому ... это своего рода путают – Dan

+0

Проверьте изменения. – mybirthname

ответ

25

Нет здесь текст из SqlBulkCopy документации в msdn

По умолчанию, основная операция копирования выполняется в изолированном операции. Операция массовой копии выполняется неконтактным способом, без возможности ее возврата. Если вам нужно откат всего или часть массовой копии при возникновении ошибки, вы можете использовать транзакцию SqlBulkCopy, выполнить операцию массовой копии в рамках существующей транзакции или зачислиться в систему System.Transactions Сделка.

EDIT: сбоев документации, в ссылке, которую я дал вам:

По умолчанию основной операции копирования является его собственная транзакцией. Когда вы выполните , выполните отдельную операцию массовой копии, создайте новый экземпляр SqlBulkCopy со строкой соединения или используйте существующий объект SqlConnection без активной транзакции.В каждом сценарии операция массового копирования создает, а затем совершает транзакции или отменяет транзакцию .

Это написано для случая внутренней объемной операции копирования, которая не по умолчанию!

using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
         connectionString, SqlBulkCopyOptions.KeepIdentity | 
         SqlBulkCopyOptions.UseInternalTransaction)) 
    { 
     .... 
    } 

Посмотрите внимательно в SqlBulkCopyOptions.UseInternalTransaction! Вы явно указываете опцию UseInternalTransaction в конструкторе класса SqlBulkCopy, чтобы явно вызвать операцию массовой копии в своей собственной транзакции, в результате чего каждая партия операции массовой копии выполнялась в рамках отдельной транзакции. Поскольку разные партии выполняются в разных транзакциях , если во время операции массового копирования возникает ошибка, все строки текущей партии будут отброшены назад, но строки из предыдущих партий останутся в базе данных.


Если необходимо выполнить откат всей операции массового копирования, так как возникает ошибка, или если основная копия должна выполняться как часть более крупного процесса, который может быть откат, вы можете предоставить объект SqlTransaction к конструктору SqlBulkCopy.

Внешняя сделка кейс.

  using (SqlTransaction transaction = 
         destinationConnection.BeginTransaction()) 
      { 
       using (SqlBulkCopy bulkCopy = new SqlBulkCopy(
          destinationConnection, SqlBulkCopyOptions.KeepIdentity, 
          transaction)) 
       { 
        .... 
       } 
      } 

Как я уже сказал в попрошайничество ответ нет, то вы должны использовать существующие транзакции или внутреннюю объемную транзакцию копирования. Прочтите файл документации, который находится в ссылке, для получения дополнительной информации.

Если вы хотите иметь транзакцию, вы должны использовать один из двух случаев, которые я написал.

+0

В этих документах говорится: * По умолчанию операция массового копирования - это его собственная транзакция. Когда вы хотите выполнить выделенную операцию массовой копии, создайте новый экземпляр SqlBulkCopy со строкой подключения или используйте существующий объект SqlConnection без активной транзакции. В каждом сценарии операция массового копирования создает, а затем совершает или откатывает транзакцию. * Также означает, что если я использую 'using (SqlBulkCopy bulkCopy = new SqlBulkCopy (connection)) вместо того, что у меня есть, тогда это будет в транзакции? Или лучше позвонить самому 'con.BeginTransaction'? – Dan

+0

@ Дайте проверить редактирование и скажите, если что-то неясно! – mybirthname

+1

Спасибо, это понятно. – Dan

Смежные вопросы