我尝试创建一个 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# 技能有限,因为我不太专业地使用它。
我在网上尝试了一些建议,例如
我正在将 SQL Server 2019 与 Visual Studio 2019 结合使用
这恰好是设计使然或者是 SSIS 上的错误。一旦进入预执行阶段(运行时),连接总是会丢失或重置为空。重新实例化连接似乎有所帮助,并且可能是在当前版本的 Visual Studio 上继续运行的唯一方法。从这个链接Custom ConnectionManager在运行时总是返回null它显示其他人也有同样的问题。