2017-02-14 56 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); 
    } 

每一次,你會得到正確的執行狀態。不確定爲什麼連接不能被重用,但保持連接儘可能短暫是一個好主意 - 這是另一個證明。