Я в основном из базы данных и нового в .net. Пожалуйста, несите меня, если мой вопрос звучит глупо.
Я использую SqlBulkCopy в своем коде для передачи данных с одного SQL Server на другой. Но он часто не работает из-за сетевых проблем. Чтобы избежать этого, я планирую сделать две вещи
Уменьшите размер партии (от 5000 до 1000) и увеличьте время ожидания (от 3 минут до 1 мин)
Реализация логики повтора
Мой вопрос:
Пример кода, который я использую:
private void BulkCopyTable(string schemaName, string tableName)
{using (var reader = srcConnection.ExecuteReader($"select * from [{SourceDBName}].[{schemaName}].[{tableName}]"))
{
const SqlBulkCopyOptions bulkCopyOptions = SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.FireTriggers |
SqlBulkCopyOptions.KeepNulls |
SqlBulkCopyOptions.KeepIdentity;
using (var bcp = new SqlBulkCopy(dstConnection.ConnectionString, bulkCopyOptions))
{
const int threeMinutes = 60*3;
bcp.BulkCopyTimeout = threeMinutes; //Timeout is for a single batch
bcp.BatchSize = 5000;
bcp.DestinationTableName = $"[{DestinationDB}].[{schemaName}].[{tableName}]";
bcp.EnableStreaming = true;
foreach (var col in table.Columns.Cast<Column>().Where(c => !c.Computed))
{
bcp.ColumnMappings.Add(col.Name, col.Name);
}
bcp.WriteToServer(reader);
}
}
}
Простой подход:
SqlBulkCopy
нуждается в запросе метаданных для каждого вызова WriteToServer
. Поэтому не делайте партии слишком маленькими. Эксперимент. #temp
а прочную, чтобы вы могли потерять соединение и продолжить). insert...select
в качестве последнего шага для перемещения строк из таблицы temp в реальную таблицу. Этот танец разбивает работу на повторные партии, но действует так, как если бы это была одна транзакция.
Если вам не нужна атомарность, вы можете оставить ее на шаге (1).