Проверка компонента потока данных
Метод Validate базового класса PipelineComponent предназначен для того, чтобы не допустить исполнения неправильно настроенного компонента. С помощью этого метода можно убедиться, что у компонента есть нужное число входных и выходных объектов, его пользовательские свойства имеют допустимые значения и что любые нужные соединения заданы. Этот метод также используется для проверки правильности типов данных во входной и выходной коллекциях столбцов и что свойство DTSUsageType всех столбцов настроено в соответствии с типом компонента. Реализация метода в базовом классе участвует в проверке: она проверяет коллекцию входных столбцов компонента, гарантируя, что каждый столбец этой коллекции ссылается на столбец коллекции IDTSOutputCollection100 вышестоящего компонента.
Метод Validate
Метод Validate неоднократно вызывается при изменении компонента в конструкторе служб SSIS. Отзыв для конструктора и пользователей компонента можно обеспечить через возвращаемое значение DTSValidationStatus из перечисления, а также с помощью выводимых предупреждений и сообщений об ошибках. Перечисление DTSValidationStatus содержит три значения, указывающие на различные степени неудачи, и четвертое, VS_ISVALID, которое указывает, что компонент настроен правильно и готов к выполнению.
Значение VS_NEEDSNEWMETADATA указывает, что в данных ComponentMetaData есть ошибка и компонент может ее исправить. Если компонент обнаруживает ошибку в метаданных, которую может исправить, ее не следует исправлять в методе Validate и во время проверки не следует изменять метаданные ComponentMetaData. Вместо этого метод Validate должен вернуть только значение VS_NEEDSNEWMETADATA, а компонент должен исправить метаданные с помощью вызова метода ReinitializeMetaData, как будет описано ниже в этом разделе.
Значение VS_ISBROKEN указывает, что компонент содержит ошибку, которую можно исправить, изменив компонент в конструкторе. Такая ошибка обычно вызвана неправильно заданным или настроенным пользовательским свойством или обязательным соединением.
Последнее значение ошибки — VS_ISCORRUPT: оно указывает, что компонент обнаружил ошибки, которые могут возникнуть только в случае непосредственного изменения свойства ComponentMetaData редактированием XML-кода программного пакета или с помощью модели объектов. Например, такая ошибка может возникнуть, если в компоненте добавлен только один входной параметр, но при проверке обнаруживается, что в метаданных ComponentMetaData их указано несколько. Ошибки, о которых сообщает этот код возврата, можно исправить только сбросом компонента с помощью кнопки Сбросить в диалоговом окне расширенного редактора.
Кроме возвращения кода ошибки, компоненты предоставляют отзыв с помощью предупреждений и сообщений об ошибках, выдаваемых во время проверки. Этот механизм поддерживают методы FireWarning и FireError. При их вызове сообщения о соответствующих событиях публикуются в окне списка ошибок среды разработки Business Intelligence Development Studio. Затем разработчики компонента могут предоставить отзыв пользователям о происшедших ошибках и, по возможности, о способах их исправления.
В следующем примере кода показана переопределенная реализация метода 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
Метод ReinitializeMetaData вызывается конструктором служб SSIS каждый раз, когда компонент возвращает значение VS_NEEDSNEWMETADATA после вызова метода Validate. Компоненты должны содержать код, который обнаруживает и устраняет проблемы, выявленные компонентом во время проверки.
В этом примере показан компонент, обнаруживающий недостатки в ходе проверки и исправляющий их с помощью метода 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
|