我有一个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。
答案 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);
}
每次都能获得正确的执行状态。不确定为什么连接不能重复使用,但保持连接尽可能短暂是一个好主意 - 这是另一个证明。