Я вставляю данные через 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
, который берет строку, является ли лучший способ заставить ее произойти в транзакции?
public void testBulkInsert(string connection, string table, DataTable dt)
{
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.DestinationTableName = table;
bulkCopy.WriteToServer(dt);
}
}
Я считаю, что документы немного неясны в этом вопросе, поскольку они изначально заявляют, что
По умолчанию операция массового копирования выполняется как изолированная операция. Операция массовой копии выполняется не трансактным способом, без возможности ее возврата
но потом
По умолчанию операция массового копирования является собственной транзакцией. Когда вы хотите выполнить выделенную операцию массовой копии, создайте новый экземпляр 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();
}
}
}
Нет здесь текст из документации 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))
{
....
}
}
Как я сказал в попрошайничестве, ответ отрицательный, вы должны использовать существующую транзакцию или транзакцию внутренней массовой копии. Прочтите файл документации, который находится в ссылке, для получения дополнительной информации.
Если вы хотите иметь транзакцию, вы должны использовать один из двух случаев, которые я написал.