创建 SSIS 自定义组件 - PreExecute 方法无法获取连接管理器

问题描述 投票:0回答:1

我尝试创建一个 SSIS 自定义组件来从 Salesforce 检索数据。我让自定义连接管理器项目工作并验证,并且自定义源工作并获取连接,直到它到达 PreExecute 方法。我注意到在 PreExecute 方法上设置断点不起作用,因此我使用了 MessageBox.Show() 并发现在执行将数据检索到 SSIS 输出 (OutputCollection) 时,指定的连接管理器始终为 null。然而,连接管理器和源组件在 SetComponentProperty 方法之前工作得很好,因为我可以将输出列添加到 SSIS 包中。

我得到的错误是“[MyCustomComponent Source [8]] 错误:System.NullReferenceException:未将对象引用设置为对象的实例。 在 MyCustomComponent.MyCustomComponentSource.MyCustomComponentSource.PreExecute() 在 Microsoft.SqlServer.Dts.Pipeline.ManagedComponentHost.HostPreExecute(IDTSManagedComponentWrapper100 包装器)”

代码是...

 [DtsPipelineComponent(DisplayName = "MyCustomComponent", ComponentType = ComponentType.SourceAdapter, IconResource = "MyCustomComponent.Resources.Icon1.ico")]
    public class MyCustomComponent : PipelineComponent
    {
        private ForceClient sfConnection;
        private SFConnectionManager.SFConnectionManager ksConnectionManager;

        private string sfQuery = string.Empty;
        //private string sfQuery = "SELECT id, name, AccountNumber, BillingCity FROM Account";

        public int[] mapOutputColsToBufferCols;

        public override void AcquireConnections(object transaction)
        {
            //base.AcquireConnections(transaction);

            if (ComponentMetaData.RuntimeConnectionCollection[0].ConnectionManager != null)
            {
                ConnectionManager connectionManager = Microsoft.SqlServer.Dts.Runtime.DtsConvert.GetWrapper(
                  ComponentMetaData.RuntimeConnectionCollection[0].ConnectionManager);

                this.ksConnectionManager = connectionManager.InnerObject as SFConnectionManager.SFConnectionManager;

                if (this.ksConnectionManager == null)
                    throw new Exception("Couldn't get the Salesforce connection manager, ");

                this.sfConnection = this.ksConnectionManager.AcquireConnection(transaction) as ForceClient;
            }
        }
        public override void ReleaseConnections()
        {
            if (ksConnectionManager != null)
            {
                this.ksConnectionManager.ReleaseConnection(sfConnection);
            }
        }
        public override void ReinitializeMetaData()
        {
            this.ComponentMetaData.RemoveInvalidInputColumns();
            base.ReinitializeMetaData();
        }
        public override DTSValidationStatus Validate()
        {
            return base.Validate();
        }
        public override IDTSCustomProperty100 SetComponentProperty(string propertyName, object propertyValue)
        {
            if (propertyName == "SOAQ" && ComponentMetaData.OutputCollection[0].OutputColumnCollection.Count == 0)
            {
                AddOutputColumns(propertyValue.ToString());
            }

            return base.SetComponentProperty(propertyName, propertyValue);
        }
        public override void ProvideComponentProperties()
        {
            // Reset the component.
            base.ProvideComponentProperties();
            base.RemoveAllInputsOutputsAndCustomProperties();
            ComponentMetaData.RuntimeConnectionCollection.RemoveAll();

            IDTSCustomProperty100 sf_query = ComponentMetaData.CustomPropertyCollection.New();
            sf_query.Name = "SOAQ";
            sf_query.Description = "Salesforce Connector Query";

            //Commenting query out as it will be provided manauuly and later entered in from form.
            sf_query.Value = sfQuery;

            IDTSOutput100 output = ComponentMetaData.OutputCollection.New();
            output.Name = "SFOutput";

            IDTSRuntimeConnection100 connection = ComponentMetaData.RuntimeConnectionCollection.New();
            connection.Name = "K Salesforce";
        }
        public override void PreExecute()
        {
            base.PreExecute();

            IDTSOutput100 output = ComponentMetaData.OutputCollection[0];
            mapOutputColsToBufferCols = new int[output.OutputColumnCollection.Count];

            for (int i = 0; i < ComponentMetaData.OutputCollection[0].OutputColumnCollection.Count; i++)
            {
                // Here, "i" is the column count in the component's outputcolumncollection
                // and the value of mapOutputColsToBufferCols[i] is the index of the corresponding column in the
                // buffer.
                mapOutputColsToBufferCols[i] = BufferManager.FindColumnByLineageID(output.Buffer, output.OutputColumnCollection[i].LineageID);
            }
        }

请注意,当到达 PreExecute 时,连接变量 sfConnection 和 ksConnectionManager 重置为 null。我不确定在 PreExecute 中创建新实例是否会有帮助(我尝试过),但我的 C# 技能有限,因为我不太专业地使用它。

我在网上尝试了一些建议,例如

  • 将平台目标更改为 VS 上的任何 CPU(我还尝试了 x86 和 x64)。
  • 更改 SSIS 包上的保护级别。
  • 将包级别的延迟验证属性更改为 True。
  • 将“run64bitRuntime”设置为 False

我正在将 SQL Server 2019 与 Visual Studio 2019 结合使用

c#-4.0 ssis sql-server-data-tools custom-component ssis-connection-manager
1个回答
0
投票

这恰好是设计使然或者是 SSIS 上的错误。一旦进入预执行阶段(运行时),连接总是会丢失或重置为空。重新实例化连接似乎有所帮助,并且可能是在当前版本的 Visual Studio 上继续运行的唯一方法。从这个链接Custom ConnectionManager在运行时总是返回null它显示其他人也有同样的问题。

© www.soinside.com 2019 - 2024. All rights reserved.