我正在使用Sql Bulk Copy.Write To Server(C#)来复制数十亿行,这需要几个小时才能完成。有时我需要停止一些紧急任务的操作,但我不知道该怎么做。我可以在通知事件到达时执行某些操作(使用Sql Bulk Copy.NotifyAfter和Sql Bulk Copy.SqlRowsCopied)吗?
答案 0 :(得分:3)
如果用户想要从事件中取消操作,则中止 可以使用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
答案 1 :(得分:1)
我可以在通知事件到达时做些什么吗
作为SQL管理员,您始终可以找到运行批量加载的会话和KILL它,如下所示:
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。例如
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;
}
}
}
答案 2 :(得分:0)
如果您在一个单独的进程中运行SQLBulkCopy,那么在需要时终止该进程将是微不足道的。
答案 3 :(得分:0)
您可以尝试修改sql查询并以块的形式处理数据,例如,每个请求1000个。如果你需要停止操作,记住块大小和数量,停止sql操作,做你需要的,并继续sql操作。
您也可以像users_id
一样制作自己的PaueOperationToken
。
以下是CancelToken
的{{3}}。