验证数据流组件
PipelineComponent 基类的 Validate 方法用于防止执行未正确配置的组件。 使用此方法可验证组件是否具有预期数量的输入和输出对象,组件的自定义属性是否具有可接受的值,以及所需的任何连接是否都已指定。 使用此方法还可以验证输入和输出集合中的列是否具有正确的数据类型,以及是否为组件正确设置了每列的 DTSUsageType。 基类实现通过检查组件的输入列集合并确保该集合中的每一列都引用上游组件的 IDTSOutputCollection100 中的一列来支持验证过程。
Validate 方法
在 SSIS 设计器中编辑组件时,系统会反复调用 Validate 方法。 通过 DTSValidationStatus 枚举返回的值以及发布警告和错误,可以向设计器和组件用户提供反馈。 DTSValidationStatus 枚举包含三个指示各种失败阶段的值,还有第四个值,即 VS_ISVALID,它指示组件是否配置正确并且可以执行。
VS_NEEDSNEWMETADATA 值指示在 ComponentMetaData 中存在错误,并且组件可以修复这些错误。 如果组件遇到它可修复的元数据错误,它不应在 Validate 方法中修复该错误,并且不应在验证期间修改 ComponentMetaData。 如本节后面所述,Validate 方法应只返回 VS_NEEDSNEWMETADATA,并且组件应在对 ReinitializeMetaData 方法的调用中修复该错误。
VS_ISBROKEN 值指示组件具有可通过在设计器中进行编辑来更正的错误。 导致该错误的原因通常是没有指定或没有正确设置自定义属性或所需连接。
最后一个错误值是 VS_ISCORRUPT,它指示组件已发现仅应该在编辑包 XML 或使用对象模型直接修改 ComponentMetaData 属性时出现的错误。 例如,当组件只添加了一个输入,但是验证操作却发现 ComponentMetaData 中存在多个输入时,此类错误将会发生。 生成此返回值的错误只能通过使用**“高级编辑器”对话框中的“重置”**按钮重置组件才能修复。
除了返回错误值,组件还通过在验证过程中发布警告和错误来提供反馈。 FireWarning 和 FireError 方法提供了此机制。 调用这些方法时,这些事件会发布在 SQL Server Data Tools (SSDT) 的**“错误列表”**窗口中。 然后,组件开发人员可以直接向用户提供有关已发生错误的反馈,并且在适当的情况下说明如何更正它们。
下面的代码示例演示 Validate 的重写实现。
public override DTSValidationStatus Validate()
{
bool pbCancel = false;
// Validate that there is one input.
if (ComponentMetaData.InputCollection.Count != 1)
{
ComponentMetaData.FireError(0, ComponentMetaData.Name, "Incorrect number of inputs.", "", 0, out pbCancel);
return DTSValidationStatus.VS_ISCORRUPT;
}
// Validate that the UserName custom property is set.
if (ComponentMetaData.CustomPropertyCollection["UserName"].Value == null || ((string)ComponentMetaData.CustomPropertyCollection["UserName"].Value).Length == 0)
{
ComponentMetaData.FireError(0, ComponentMetaData.Name, "The UserName property must be set.", "", 0, out pbCancel);
return DTSValidationStatus.VS_ISBROKEN;
}
// Validate that there is one output.
if (ComponentMetaData.OutputCollection.Count != 1)
{
ComponentMetaData.FireError(0, ComponentMetaData.Name, "Incorrect number of outputs.", "", 0, out pbCancel);
return DTSValidationStatus.VS_ISCORRUPT;
}
// Let the base class verify that the input column reflects the output
// of the upstream component.
return base.Validate();
}
Public Overrides Function Validate() As DTSValidationStatus
Dim pbCancel As Boolean = False
' Validate that there is one input.
If Not (ComponentMetaData.InputCollection.Count = 1) Then
ComponentMetaData.FireError(0, ComponentMetaData.Name, "Incorrect number of inputs.", "", 0, pbCancel)
Return DTSValidationStatus.VS_ISCORRUPT
End If
' Validate that the UserName custom property is set.
If ComponentMetaData.CustomPropertyCollection("UserName").Value Is Nothing OrElse CType(ComponentMetaData.CustomPropertyCollection("UserName").Value, String).Length = 0 Then
ComponentMetaData.FireError(0, ComponentMetaData.Name, "The UserName property must be set.", "", 0, pbCancel)
Return DTSValidationStatus.VS_ISBROKEN
End If
' Validate that there is one output.
If Not (ComponentMetaData.OutputCollection.Count = 1) Then
ComponentMetaData.FireError(0, ComponentMetaData.Name, "Incorrect number of outputs.", "", 0, pbCancel)
Return DTSValidationStatus.VS_ISCORRUPT
End If
' Let the base class verify that the input column reflects the output
' of the upstream component.
Return MyBase.Validate
End Function
ReinitializeMetaData 方法
每当您编辑从其 Validate 方法返回 VS_NEEDSNEWMETADATA 的组件时,SSIS 设计器都会调用 ReinitializeMetaData 方法。 组件应包含用于检测和更正在验证过程中由组件标识的问题的代码。
下面的示例演示一个在验证过程中检测问题并在 ReinitializeMetaData 方法中修复这些错误的组件。
private bool areInputColumnsValid = true;
public override DTSValidationStatus Validate()
{
IDTSInput100 input = ComponentMetaData.InputCollection[0];
IDTSVirtualInput100 vInput = input.GetVirtualInput();
bool Cancel = false;
foreach (IDTSInputColumn100 column in input.InputColumnCollection)
{
try
{
IDTSVirtualInputColumn100 vColumn = vInput.VirtualInputColumnCollection.GetVirtualInputColumnByLineageID(column.LineageID);
}
catch
{
ComponentMetaData.FireError(0, ComponentMetaData.Name, "The input column " + column.IdentificationString + " does not match a column in the upstream component.", "", 0, out Cancel);
areInputColumnsValid = false;
return DTSValidationStatus.VS_NEEDSNEWMETADATA;
}
}
return DTSValidationStatus.VS_ISVALID;
}
public override void ReinitializeMetaData()
{
if (!areInputColumnsValid)
{
IDTSInput100 input = ComponentMetaData.InputCollection[0];
IDTSVirtualInput100 vInput = input.GetVirtualInput();
foreach (IDTSInputColumn100 column in input.InputColumnCollection)
{
IDTSVirtualInputColumn100 vColumn = vInput.VirtualInputColumnCollection.GetVirtualInputColumnByLineageID(column.LineageID);
if (vColumn == null)
input.InputColumnCollection.RemoveObjectByID(column.ID);
}
areInputColumnsValid = true;
}
}
Private areInputColumnsValid As Boolean = True
Public Overrides Function Validate() As DTSValidationStatus
Dim input As IDTSInput100 = ComponentMetaData.InputCollection(0)
Dim vInput As IDTSVirtualInput100 = input.GetVirtualInput
Dim Cancel As Boolean = False
For Each column As IDTSInputColumn100 In input.InputColumnCollection
Try
Dim vColumn As IDTSVirtualInputColumn100 = vInput.VirtualInputColumnCollection.GetVirtualInputColumnByLineageID(column.LineageID)
Catch
ComponentMetaData.FireError(0, ComponentMetaData.Name, "The input column " + column.IdentificationString + " does not match a column in the upstream component.", "", 0, Cancel)
areInputColumnsValid = False
Return DTSValidationStatus.VS_NEEDSNEWMETADATA
End Try
Next
Return DTSValidationStatus.VS_ISVALID
End Function
Public Overrides Sub ReinitializeMetaData()
If Not areInputColumnsValid Then
Dim input As IDTSInput100 = ComponentMetaData.InputCollection(0)
Dim vInput As IDTSVirtualInput100 = input.GetVirtualInput
For Each column As IDTSInputColumn100 In input.InputColumnCollection
Dim vColumn As IDTSVirtualInputColumn100 = vInput.VirtualInputColumnCollection.GetVirtualInputColumnByLineageID(column.LineageID)
If vColumn Is Nothing Then
input.InputColumnCollection.RemoveObjectByID(column.ID)
End If
Next
areInputColumnsValid = True
End If
End Sub
|