Validando um componente de fluxo de dados
O método Validate da classe base PipelineComponent é fornecido para impedir a execução de um componente que não está configurado corretamente. Utilize esse método para verificar se um componente possui o número esperado de objetos de entrada e saída, se as propriedades personalizadas do componente possuem valores aceitáveis e se há conexões especificadas, caso necessário. Utilize esse método também para verificar se as colunas nas coleções de entrada e saída possuem os tipos de dados corretos e se o DTSUsageType de cada coluna está definido adequadamente para o componente. A implementação da classe base ajuda no processo de validação pois verifica a coleção de colunas de entrada do componente e se cada coluna da coleção se refere a uma coluna do IDTSOutputCollection100 do componente upstream.
Método Validate
O método Validate é chamado repetidamente quando um componente é editado no Designer SSIS. Você pode fornecer comentários ao designer e a usuários do componente através do valor de retorno de enumeração DTSValidationStatus e postando avisos e erros. A enumeração DTSValidationStatus contém três valores que indicam vários estágios da falha e um quarto valor, VS_ISVALID, que indica se o componente foi configurado corretamente e se está pronto para ser executado.
O valor VS_NEEDSNEWMETADATA indica que existe um erro no ComponentMetaData, e que o componente pode reparar os erros. Se um componente encontrar um erro de metadados que possa reparar, não deverá corrigir o erro no método Validate e ComponentMetaData não deverá ser modificado durante a validação. Em vez disso, o método Validate deve retornar apenas VS_NEEDSNEWMETADATA e o componente deve reparar o erro em uma chamada para o método ReinitializeMetaData, conforme descrito posteriormente nessa seção.
O valor VS_ISBROKEN indica que o componente tem um erro que pode ser retificado editando o componente no designer. O erro costuma ser causado por uma propriedade personalizada ou uma conexão exigeida que não foi especificada ou foi definida incorretamente.
O valor de erro final é VS_ISCORRUPT, que indica que o componente descobriu erros que só devem ocorrer quando a propriedade ComponentMetaData é modificada diretamente, através da edição do pacote XML ou do uso do modelo de objeto. Por exemplo, esse tipo de erro ocorre quando um componente adiciona uma única entrada, mas a validação descobre que existe mais de uma entrada no ComponentMetaData. Erros que geram esse valor de retorno só podem ser reparados através da redefinição do componente utilizando o botão Redefinir na caixa de diálogo Editor Avançado.
Além de retornar valores de erro, componentes fornecem comentários postando avisos ou erros durante a validação. Os métodos FireWarning e FireError fornecem esse mecanismo. Quando esses métodos são chamados, esses eventos são postados na janela Lista de Erros do SSDT (SQL Server Data Tools). Desenvolvedores de componente podem fornecer comentários diretos a usuários sobre os erros que ocorreram e, se apropriado, como corrigi-los.
O exemplo de código a seguir mostra uma implementação substituída de 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
Método ReinitializeMetaData
O método ReinitializeMetaData é chamado pelo SSIS Designer sempre que você edita um componente que retorna VS_NEEDSNEWMETADATA do seu método Validate. Componentes devem conter código que detecta e corrige os problemas identificados pelo componente durante a validação.
O exemplo a seguir mostra um componente que detecta problemas durante a validação e corrige-os no método 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
|