2017-02-14 55 views
4

我的影片启动另一个SSIS包在的foreach容器的SSIS包;因为一旦它启动了所有必须启动的包,容器就报告完成,我需要一种方法让它等到所有“子”包完成。轮询SSIS执行状态

所以我实现了一个小的睡眠等待循环,基本上拉Execution对象关SSISDB为ID的,我感兴趣的

我面临的问题,是一个总计0 Dts.Events.FireProgress事件被解雇,如果我取消在do循环的Dts.Events.FireInformation呼叫,然后每一秒我得到一个消息报道说,23包仍在运行...除非我在SSISDB的活动操作检查窗口,我看到大部分已完成已经和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; 
} 

GetExecutionIDs函数只是从我的元数据库中返回子包的所有执行ID。

+0

我没有用'C#'SSIS的,但你不能'你可以在SSDT execute'在'C#'包?这样你在继续处理之前得到一个结果。 – NickyvV

+0

@NickyvV foreach循环迭代是行的元数据,以确定如何处理参数封装 - 我正在同一个包20+情况下,在一个循环,我需要他们同时运行(这部分作品)。问题是,如果我什么都不做,那么“主”包会在“子”包完成运行之前报告完成,我不能这样做。上面是一个*脚本任务*,它跟在foreach容器之后,基本上等待所有“子”包完成。我不能将'execute'作为阻塞调用,因为我需要它们并发。 –

+0

此外,由于某种原因,我不能在任何地方该脚本打破 - 我的意思是我*可*把断点,但他们从来不打*尽管显示在脚本任务框的红点*的SSIS控制流。 –

回答

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

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