C# 轮询SSIS执行状态
我有一个SSIS包,它正在Foreach容器中启动另一个SSIS包;因为容器在启动它必须启动的所有包时就报告完成,所以我需要一种方法使它等待所有“子”包完成 因此,我实现了一个小的sleep wait循环,它基本上将我感兴趣的ID的C# 轮询SSIS执行状态,c#,ssis,sql-server-2014,C#,Ssis,Sql Server 2014,我有一个SSIS包,它正在Foreach容器中启动另一个SSIS包;因为容器在启动它必须启动的所有包时就报告完成,所以我需要一种方法使它等待所有“子”包完成 因此,我实现了一个小的sleep wait循环,它基本上将我感兴趣的ID的执行对象从SSISDB中拉出来 我面临的问题是,总共有0个Dts.Events.FireProgress事件被触发,如果我在do循环中取消对Dts.Events.FireInformation调用的注释,那么每秒我都会收到一条消息,报告说23个包仍在运行。。。除非我签
执行
对象从SSISDB中拉出来
我面临的问题是,总共有0个Dts.Events.FireProgress
事件被触发,如果我在do
循环中取消对Dts.Events.FireInformation
调用的注释,那么每秒我都会收到一条消息,报告说23个包仍在运行。。。除非我签入SSIDB的活动操作窗口,否则我会看到大多数操作已经完成,3或4个操作实际上正在运行
我做错了什么,为什么runningCount
不包含实际运行的执行数
using ssis = Microsoft.SqlServer.Management.IntegrationServices;
public void Main()
{
const string serverName = "REDACTED";
const string catalogName = "SSISDB";
var ssisConnectionString = $"Data Source={serverName};Initial Catalog=msdb;Integrated Security=SSPI;";
var ids = GetExecutionIDs(serverName);
var idCount = ids.Count();
var previousCount = -1;
var iterations = 0;
try
{
var fireAgain = true;
const int secondsToSleep = 1;
var sleepTime = TimeSpan.FromSeconds(secondsToSleep);
var maxIterations = TimeSpan.FromHours(1).TotalSeconds / sleepTime.TotalSeconds;
IDictionary<long, ssis.Operation.ServerOperationStatus> catalogExecutions;
using (var connection = new SqlConnection(ssisConnectionString))
{
var server = new ssis.IntegrationServices(connection);
var catalog = server.Catalogs[catalogName];
do
{
catalogExecutions = catalog.Executions
.Where(execution => ids.Contains(execution.Id))
.ToDictionary(execution => execution.Id, execution => execution.Status);
var runningCount = catalogExecutions.Count(kvp => kvp.Value == ssis.Operation.ServerOperationStatus.Running);
System.Threading.Thread.Sleep(sleepTime);
//Dts.Events.FireInformation(0, "ScriptMain", $"{runningCount} packages still running.", string.Empty, 0, ref fireAgain);
if (runningCount != previousCount)
{
previousCount = runningCount;
decimal completed = idCount - runningCount;
decimal percentCompleted = completed / idCount;
Dts.Events.FireProgress($"Waiting... {completed}/{idCount} completed", Convert.ToInt32(100 * percentCompleted), 0, 0, "", ref fireAgain);
}
iterations++;
if (iterations >= maxIterations)
{
Dts.Events.FireWarning(0, "ScriptMain", $"Timeout expired, requesting cancellation.", string.Empty, 0);
Dts.Events.FireQueryCancel();
Dts.TaskResult = (int)Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Canceled;
return;
}
}
while (catalogExecutions.Any(kvp => kvp.Value == ssis.Operation.ServerOperationStatus.Running));
}
}
catch (Exception exception)
{
if (exception.InnerException != null)
{
Dts.Events.FireError(0, "ScriptMain", exception.InnerException.ToString(), string.Empty, 0);
}
Dts.Events.FireError(0, "ScriptMain", exception.ToString(), string.Empty, 0);
Dts.Log(exception.ToString(), 0, new byte[0]);
Dts.TaskResult = (int)ScriptResults.Failure;
return;
}
Dts.TaskResult = (int)ScriptResults.Success;
}
使用ssis=Microsoft.SqlServer.Management.IntegrationServices;
公共图书馆
{
常量字符串serverName=“已编辑”;
常量字符串catalogName=“SSISDB”;
var ssinconnectionstring=$“数据源={serverName};初始目录=msdb;集成安全性=SSPI;”;
var id=getExecutionId(服务器名);
var idCount=ids.Count();
var previousCount=-1;
var迭代次数=0;
尝试
{
var=true;
const int secondsToSleep=1;
var sleepTime=TimeSpan.FromSeconds(secondsToSleep);
var maxIterations=TimeSpan.FromHours(1).TotalSeconds/sleepTime.TotalSeconds;
词典目录;
使用(var连接=新的SqlConnection(ssisConnectionString))
{
var服务器=新ssis.IntegrationServices(连接);
var catalog=server.Catalogs[catalogName];
做
{
catalogExecutions=catalog.Executions
.Where(execution=>ids.Contains(execution.Id))
.ToDictionary(execution=>execution.Id,execution=>execution.Status);
var runningCount=catalogExecutions.Count(kvp=>kvp.Value==ssis.Operation.ServerOperationStatus.Running);
系统。线程。线程。睡眠(睡眠时间);
//FireInformation(0,“ScriptMain”,$“{runningCount}包仍在运行。”,string.Empty,0,再次引用FireInformation);
if(runningCount!=上一次计数)
{
previousCount=运行计数;
十进制完成=idCount-runningCount;
小数百分比完成=完成/idCount;
Dts.Events.FireProgress($“Waiting…{completed}/{idCount}completed”,Convert.ToInt32(100*percentCompleted),0,0,”,再次引用FireProgress);
}
迭代++;
如果(迭代次数>=最大迭代次数)
{
Dts.Events.FireWarning(0,“ScriptMain”,“超时已过期,请求取消)”,string.Empty,0);
FireQueryCancel();
Dts.TaskResult=(int)Microsoft.SqlServer.Dts.Runtime.dtsesecresult.cancelled;
返回;
}
}
while(catalogExecutions.Any(kvp=>kvp.Value==ssis.Operation.ServerOperationStatus.Running));
}
}
捕获(异常)
{
if(exception.InnerException!=null)
{
FireError(0,“ScriptMain”,exception.InnerException.ToString(),string.Empty,0);
}
Dts.Events.FireError(0,“ScriptMain”,exception.ToString(),string.Empty,0);
Log(exception.ToString(),0,新字节[0]);
Dts.TaskResult=(int)ScriptResults.Failure;
返回;
}
Dts.TaskResult=(int)ScriptResults.Success;
}
getExecutionId
函数只是从我的元数据数据库中返回子包的所有执行ID。问题在于每次迭代都使用相同的连接。把这个翻过来:
为此:
do
{
using (var connection = new SqlConnection(ssisConnectionString))
{
var server = new ssis.IntegrationServices(connection);
var catalog = server.Catalogs[catalogName];
catalogExecutions = catalog.Executions
.Where(execution => ids.Contains(execution.Id))
.ToDictionary(execution => execution.Id, execution => execution.Status);
}
每次都会得到正确的执行状态。不知道为什么连接不能被重用,但保持连接尽可能短的寿命始终是一个好主意,这是另一个证明。我没有在SSIS中使用
c#
,但是你不能在c#
中执行包吗?这样,您就可以在继续处理之前返回一个结果。@NickyvV foreach循环正在迭代元数据行,以确定使用什么参数化包-我正在循环中运行同一个包的20多个实例,并且需要它们同时运行(该部分工作)。问题是,如果我不做任何事情,那么“主”包在“子”包完成运行之前报告完成,而我不能这样做;上面是一个脚本任务,它遵循foreach容器,基本上等待所有“子”包完成。我不能让execute
成为一个阻塞调用,因为我需要它们是并发的。此外,出于某种原因,我不能在该脚本中的任何地方中断—我的意思是我可以放置断点,但它们从未被命中,尽管SSIS控制流在脚本任务框中显示了红点。
do
{
using (var connection = new SqlConnection(ssisConnectionString))
{
var server = new ssis.IntegrationServices(connection);
var catalog = server.Catalogs[catalogName];
catalogExecutions = catalog.Executions
.Where(execution => ids.Contains(execution.Id))
.ToDictionary(execution => execution.Id, execution => execution.Status);
}