Я использую Sqlâ € <Копировать.Writeâ € <Toâ € <Server (C #), чтобы скопировать миллиарды строк, и для этого требуется несколько часов. Иногда мне нужно остановить операцию для выполнения некоторых неотложных задач, но я не знаю, как это сделать. Могу ли я что-то сделать при поступлении события уведомления (с помощью Sqlâ <Bulkâ <Copy.NotifyAfter и Sqlâ € <Bulkâ € <Copy.SqlRowsCopied)?
Документация MSDN гласит:
Если пользователь хочет отменить операцию из события, можно использовать свойство Abort SqlRowsCopiedEventArgs.
Поэтому следующий код должен сделать трюк:
SqlBulkCopy cp = new SqlBulkCopy("your connection string");
cp.NotifyAfter = 1000; // use here whatever number floats your boat
cp.SqlRowsCopied += (sender, eventArgs) => eventArgs.Abort = true; // add some more conditions here
Могу ли я что-то сделать при поступлении уведомления
В качестве администратора SQL вы всегда можете найти сеанс, на котором загружается объемная загрузка, и KILL it, например:
declare @spid int = (
select session_id
from sys.dm_exec_requests
where command = 'BULK INSERT')
if @spid is not null
begin
declare @sql varchar(200) = concat('kill ',@spid)
exec ( @sql )
end
Если вы хотите сделать это в своем коде, используйте версию WriteToServer Async, которая принимает токен отмены. например
static void Main(string[] args)
{
using (var src = new SqlConnection("server=.;database=tempdb;integrated security=true"))
using (var dest = new SqlConnection("server=.;database=tempdb;integrated security=true"))
{
src.Open();
dest.Open();
var cmd = new SqlCommand("create table #t(id int)", dest);
cmd.ExecuteNonQuery();
bool cancel = false;
var cancelationTokenSource = new CancellationTokenSource();
var srcCmd = new SqlCommand("select row_number() over (order by (select null)) id from sys.objects o, sys.columns c, sys.columns c2", src);
using (var rdr = srcCmd.ExecuteReader())
{
var bc = new SqlBulkCopy(dest);
bc.NotifyAfter = 10000;
bc.SqlRowsCopied += (s, a) =>
{
Console.WriteLine($"{a.RowsCopied} rows copied");
if (cancel)
{
dest.Close();
}
};
bc.DestinationTableName = "#t";
bc.ColumnMappings.Add(new SqlBulkCopyColumnMapping("id", "id"));
var task = bc.WriteToServerAsync(rdr, cancelationTokenSource.Token);
Console.WriteLine("Hit any key to cancel the bulk load");
while (!task.Wait(1000))
{
if (Console.KeyAvailable)
{
cancelationTokenSource.Cancel();
try
{
task.Wait();
}
catch (AggregateException ex)
{
Console.WriteLine(ex.InnerException.Message);
Console.WriteLine("WriteToServer Canceled");
break;
}
}
}
Console.WriteLine("Hit any key to exit");
return;
}
}
}