1

我正在尝试以编程方式执行一个包。SSIS 包是使用项目部署模型部署的。我以以下为例: http ://microsoft-ssis.blogspot.com/2013/01/call-ssis-2012-package-within-net.html

 // Connection to the database server where the packages are located             
    SqlConnection ssisConnection = new SqlConnection
            (@"Data Source=SSIS_SERVER;Initial Catalog=master;
               Integrated Security=SSPI;");   

// SSIS server object with connection             
    IntegrationServices ssisServer = new IntegrationServices(ssisConnection);        

// The reference to the package which you want to execute  
     // (Note: formatted for ease of reading)           
    PackageInfo ssisPackage = ssisServer
                               .Catalogs["SSISDB"]
                               .Folders["DEV_FOLDER"]
                               .Projects["TestParentChildDeployment"]
                               .Packages["Child.dtsx"];     

// Add execution parameter to override the default asynchronized execution. 
//If you leave this out the package is executed asynchronized             

    //Collection<PackageInfo.ExecutionValueParameterSet> executionParameter 
    //    = new Collection<PackageInfo.ExecutionValueParameterSet>();   

    var executionParameter = new Collection<PackageInfo
                                   .ExecutionValueParameterSet>();

    executionParameter.Add
        (new PackageInfo.ExecutionValueParameterSet 
            { 
                ObjectType = 50
                              , ParameterName = "SYNCHRONIZED"
                              , ParameterValue = 1 
            }
        );               

// Get the identifier of the execution to get the log             
    long executionIdentifier = ssisPackage.Execute (false, null, executionParameter); // Times out here <<<<

这是错误:消息=超时已过期。在操作完成之前超时时间已过或服务器没有响应。

它偶尔会成功运行一次,但通常会失败。有任何想法吗?

4

2 回答 2

0

这是我的解决方案。不是同步调用包,而是异步调用,并在调用代码中使用 ManualResetEvent 来阻塞主线程,直到包完成。

namespace Anthony.Staging.Integration.Tests
{
    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Diagnostics;
    using System.Linq;
    using System.Threading;
    using Microsoft.SqlServer.Management.Common;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    //Add references via %WINDIR%\assembly\GAC_MSIL\:
    /* Microsoft.SqlServer.ConnectionInfo
     * Microsoft.SqlServer.Management.InterationServices
     * Microsoft.SqlServer.Management.Sdk.Sfc
     * Microsoft.SqlServer.Smo
     */
    using Microsoft.SqlServer.Management.IntegrationServices;

    [TestClass]
    public class ConnectionTests
    {
        private const string connectionString = @"Data Source=Anthony\MSSQL11;Initial Catalog=SSISDB;Integrated Security=SSPI;";

        private static SqlConnection connection;

        private static ServerConnection conn;

        private static IntegrationServices ssis;

        private static string catalog = "SSISDB";

        private static string folder = "Anthony.Integration";


        [TestInitialize]
        public void MyTestInitialize()
        {
            connection = new SqlConnection(connectionString);
            ssis = new IntegrationServices(connection);
        }

        [TestMethod]
        public void CanConnect()
        {
            Assert.IsNotNull(connection);
            Assert.IsTrue(connection.State == ConnectionState.Open);
        }

        [TestMethod]
        public void CanGetKnownPackage()
        {
            try
            {
                var package = this.GetPackage(catalog, folder, "Anthony.Staging", "_Extract_Full.dtsx");
                Assert.IsNotNull(package);
            }
            catch (Exception ex)
            {
                Assert.Fail(ex.Message);
            }
        }

        [TestMethod]
        public void CanExecuteKnownPackage()
        {
            const int MAX_RETRIES = 20;
            const int RETRY_INTERVAL_SECONDS = 10; 
            const int OPERATION_TIMEOUT_MINUTES = 10;

            // get the package from the SSISCatalog and start it asynchronously
            // because starting it synchronously will time out after 30 seconds.
            var package = this.GetPackage(catalog, folder, "Anthony.Staging", "_Extract_Full.dtsx");
            var executionIdentifier = package.Execute(false, null);

            // block the main thread and kick off a timer immediately which checks execution status for an ssis execution identifier.
            var mre = new ManualResetEvent(false);
            var statusChecker = new StatusChecker(executionIdentifier, MAX_RETRIES);
            var timer = new Timer(statusChecker.CheckStatus, new StatusCheckerState(mre), new TimeSpan(0, 0, 0), new TimeSpan(0, 0, RETRY_INTERVAL_SECONDS)); 
            WaitHandle.WaitAny(new WaitHandle[] { mre }, (int)new TimeSpan(0, OPERATION_TIMEOUT_MINUTES, 0).TotalMilliseconds, false);
            mre.Dispose();
            timer.Dispose();

            // get the results
            var execution = ssis.Catalogs.Single(x => x.Name.Equals(catalog)).Executions.Single(x => x.Id.Equals(executionIdentifier));
            var errors = execution.Messages.Where(m => m.MessageType == 120).Select(m => m.Message);
            var warnings = execution.Messages.Where(m => m.MessageType == 110).Select(m => m.Message);
            Assert.AreEqual(0, errors.Count());
            Assert.AreEqual(Operation.ServerOperationStatus.Success, execution.Status);
        }

        class StatusCheckerState
        {
            public StatusCheckerState(ManualResetEvent waitHandle)
            {
                this.WaitHandle = waitHandle;
            }

            public ManualResetEvent WaitHandle { get; private set; }
        }

        class StatusChecker
        {
            private readonly long executionIdentifier;

            private int invokeCount;

            private ManualResetEvent waitHandle;

            private readonly int maximumCount;

            public StatusChecker(long executionIdentifier, int maxCount)
            {
                this.executionIdentifier = executionIdentifier;

                invokeCount = 0;
                maximumCount = maxCount;
            }

            // This method is called by the timer delegate. 
            public void CheckStatus(object state)
            {
                var localState = ((StatusCheckerState)state);
                this.waitHandle = localState.WaitHandle;

                if (invokeCount > 0)
                {
                    Debug.WriteLine("Retry attempt: {0}", invokeCount);
                }

                invokeCount++;
                if (invokeCount == maximumCount)
                {
                    // Reset the counter and signal Main.
                    invokeCount = 0;
                    waitHandle.Set();
                }

                var execution = new IntegrationServices(connection).Catalogs.Single(x => x.Name.Equals(catalog)).Executions.Single(x => x.Id.Equals(executionIdentifier));
                Debug.WriteLine("Status of execution " + executionIdentifier + " is " + execution.Status);
                if (execution.Status == Operation.ServerOperationStatus.Success)
                {
                    // Reset the counter and signal Main.
                    invokeCount = 0;
                    waitHandle.Set();
                }
            }    
        }

        [TestCleanup]
        public void MyTestCleanup()
        {
            if(connection.State == ConnectionState.Open)
                connection.Close();

            ssis = null;
        }


        private PackageInfo GetPackage(string catalog, string folder, string project, string package)
        {
            if (ssis.Catalogs.Contains(catalog))
            {
                var cat = ssis.Catalogs[catalog];

                if (cat.Folders.Contains(folder))
                {
                    var fold = cat.Folders[folder];

                    if (fold.Projects.Contains(project))
                    {
                        var proj = fold.Projects[project];

                        if (proj.Packages.Contains(package))
                        {
                            var pkg = proj.Packages[package];
                            return pkg;
                        }
                    }
                }
            }

            throw new Exception("Cannot find package!");
        }
    }
}
于 2013-02-20T12:26:34.053 回答
0

这是一些解决超时的代码......它有点脏,但效果很好:

// Get the identifier of the execution to get the log
long executionIdentifier = ssisPackage.Execute(false, null, executionParameter);

/****
* This is a shameful workaround to not having a timeout override 
* for PackageInfo.Execute.
****/
ExecutionOperation executionOperation = ssisServer.Catalogs["SSISDB"].Executions[executionIdentifier];

while (!(executionOperation.Completed))
{
  executionOperation.Refresh();
  System.Threading.Thread.Sleep(5000);
}

资料来源: https://social.msdn.microsoft.com/Forums/sqlserver/en-US/7f0967af-fdeb-4040-9c57-2fe14f2291b5/timeout-after-30-seconds-when-executing-package-via-net?论坛=sqlintegrationservices

于 2015-05-14T11:30:13.303 回答