ОБНОВЛЕНИЕ на основе принятого ответа:
bool success = false;
using (var bulkCopy = new SqlBulkCopy(connection)) //using!
{
connection.Open();
//explicit isolation level is best-practice
using (var tran = connection.BeginTransaction(IsolationLevel.ReadCommitted))
{
bulkCopy.DestinationTableName = "table";
bulkCopy.ColumnMappings...
using (var dataReader = new ObjectDataReader<SomeObject>(paths))
{
bulkCopy.WriteToServer(dataReader);
success = true;
}
tran.Commit(); //commit, will not be called if exception escapes
}
}
return success;
Я использую класс BulkCopy
для большой вставки, и он отлично работает.
После выполнения WriteToServer
и сохранения данных в базу данных
Я не знаю, все ли данные успешно сохранены, поэтому я могу вернуть true/false
потому что мне нужно сохранить все или ничего?
var bulkCopy = new SqlBulkCopy(connection);
bulkCopy.DestinationTableName = "table";
bulkCopy.ColumnMappings...
using (var dataReader = new ObjectDataReader<SomeObject>(paths))
{
try
{
bulkCopy.WriteToServer(dataReader);
}
catch(Exception ex){ ... }
}
Если вызов WriteToServer
завершился без исключений, все строки были сохранены и находятся на диске. Это просто стандартная семантика для SQL Server DML. Ничего особенного с массовой копией.
Как и все другие DML, SqlBulkCopy
- это все или ничего. За исключением случаев, когда вы настраиваете размер партии, который у вас не был.
using (var bulkCopy = new SqlBulkCopy(connection)) //using!
{
connection.Open();
//explicit isolation level is best-practice
using (var tran = connection.BeginTransaction(IsolationLevel.ReadCommitted))
{
bulkCopy.DestinationTableName = "table";
bulkCopy.ColumnMappings...
using (var dataReader = new ObjectDataReader<SomeObject>(paths))
{
//try
//{
bulkCopy.WriteToServer(dataReader, /*here you set some options*/);
//}
//catch(Exception ex){ ... } //you need no explicit try-catch here
}
tran.Commit(); //commit, will not be called if exception escapes
}
}
Я добавил вам образец кода, который я совмещал с лучшими практиками.
Нет прямого способа определить, был ли процесс успешно завершен или нет, кроме поиска / исключения любых исключений, WriteToServer()
методом WriteToServer()
.
Альтернативным подходом может быть проверка количества записей в базе данных, а затем проверка количества записей после завершения процесса. Разница - это число, которое было вставлено. Сравнение этого значения с количеством вставленных записей может дать представление об отказе или успехе. Однако это не является доказательством дурака, особенно если есть другой процесс вставки / удаления записей.
Однако эти методы в сочетании с TransactionScope
- http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx - или что-то подобное должны обеспечивать то, что вам нужно.
РЕДАКТИРОВАТЬ
По умолчанию каждая операция вставки обрабатывается как пакет; если операция не выполняется в определенной партии, тогда эта партия откатывается назад, а не вставлена перед ней.
Однако, если внутренняя транзакция применяется к объемной операции, чем отказ в любой строке может откатить весь набор результатов. Например;
using (SqlBulkCopy bulkCopy =
new SqlBulkCopy(connectionString, SqlBulkCopyOptions.KeepIdentity
| SqlBulkCopyOptions.UseInternalTransaction))
{
bulkCopy.BatchSize = 10;
bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns";
try
{
bulkCopy.WriteToServer(reader);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
bulkCopy.Close();
}
}
Ошибка в любой из вышеперечисленных операций приведет к откату всей операции. Подробнее об этом см. По адресу http://msdn.microsoft.com/en-us/library/tchktcdk.aspx .