轮询SSIS执行状态

时间:2017-02-14 19:22:16

标签: c# ssis sql-server-2014

我有一个SSIS包,可以在 Foreach容器中启动另一个SSIS包;因为容器在启动它必须启动的所有包后立即报告完成,我需要一种方法让它等到所有" child"包已经完成。

所以我实现了一个小睡眠等待循环,它基本上将--keytab个对象从SSISDB中拉出来,对我感兴趣的ID感兴趣。

我遇到的问题是,总共有0 Execution个事件被触发,如果我取消注释Dts.Events.FireProgress循环中的Dts.Events.FireInformation调用,那么每个第二,我收到一条消息,说有23个软件包仍在运行......除非我在SSISDB的 Active Operations 窗口中检查,我发现大多数已经完成,3或4个实际上正在运行。

我做错了什么,为什么不会do包含实际运行执行的数量?

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; } 函数只是从我的元数据库中返回子包的所有执行ID。

1 个答案:

答案 0 :(得分:0)

问题是您在每次迭代时都重新使用相同的连接。转过来:

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);

进入这个:

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);
    }

每次都能获得正确的执行状态。不确定为什么连接不能重复使用,但保持连接尽可能短暂是一个好主意 - 这是另一个证明。