Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Aplica-se a:SQL Server
SSIS Integration Runtime em Azure Data Factory
Objetos especiais IDTSOutput100 chamados saídas de erro podem ser adicionados aos componentes para permitir que o componente redirecione linhas que não podem ser processadas durante a execução. Os problemas que um componente pode encontrar são geralmente categorizados como erros ou truncamentos e são específicos para cada componente. Os componentes que fornecem saídas de erro dão aos usuários do componente a flexibilidade de lidar com condições de erro filtrando linhas de erro fora do conjunto de resultados, falhando o componente quando ocorre um problema ou ignorando erros e continuando.
Para implementar e dar suporte a saídas de erro em um componente, você deve primeiro definir a UsesDispositions propriedade do componente como true. Em seguida, você deve adicionar uma saída ao componente que tem sua IsErrorOut propriedade definida como true. Finalmente, o componente deve conter código que redireciona linhas para a saída de erro quando ocorrem erros ou truncamentos. Este tópico aborda essas três etapas e explica as diferenças entre saídas de erro síncronas e assíncronas.
Criando uma saída de erro
Você cria uma saída de erro chamando o New método do e, em OutputCollectionseguida, definindo a IsErrorOut propriedade da nova saída como true. Se a saída for assíncrona, nada mais deve ser feito para a saída. Se a saída for síncrona e houver outra saída síncrona para a mesma entrada, você também deverá definir as ExclusionGroup propriedades e SynchronousInputID . Ambas as propriedades devem ter os mesmos valores que a outra saída que é síncrona para a mesma entrada. Se essas propriedades não forem definidas como um valor diferente de zero, as linhas fornecidas pela entrada serão enviadas para ambas as saídas que são síncronas com a entrada.
Quando um componente encontra um erro ou truncamento durante a execução, ele prossegue com base nas configurações e ErrorRowDispositionTruncationRowDisposition propriedades da coluna de entrada ou saída, ou entrada ou saída, onde o erro ocorreu. O valor dessas propriedades deve ser definido por padrão como RD_NotUsed. Quando a saída de erro do componente é conectada a um componente downstream, essa propriedade é definida pelo usuário do componente e permite que o usuário controle como o componente lida com o erro ou truncamento.
Preenchendo colunas de erro
Quando uma saída de erro é criada, a tarefa de fluxo de dados adiciona automaticamente duas colunas à coleção de colunas de saída. Essas colunas são usadas pelos componentes para especificar a ID da coluna que causou o erro ou truncamento e para fornecer o código de erro específico do componente. Essas colunas são geradas automaticamente, mas os valores contidos nas colunas devem ser definidos pelo componente.
O método usado para definir os valores dessas colunas depende se a saída do erro é síncrona ou assíncrona. Os componentes com saídas síncronas chamam o DirectErrorRow método, discutido com mais detalhes na próxima seção, e fornecem o código de erro e os valores da coluna de erro como parâmetros. Os componentes com saídas assíncronas têm duas opções para definir os valores dessas colunas. Eles podem chamar o SetErrorInfo método do buffer de saída e fornecer os valores, ou localizar as colunas de erro no buffer usando FindColumnByLineageID e definir os valores para as colunas diretamente. No entanto, como os nomes das colunas podem ter sido alterados ou sua localização na coleção de colunas de saída pode ter sido modificada, o último método pode não ser confiável. O SetErrorInfo método define automaticamente os valores nessas colunas de erro sem ter que localizá-los manualmente.
Se você precisar obter a descrição do erro que corresponde a um código de erro específico, você pode usar o GetErrorDescriptionIDTSComponentMetaData100 método da interface, disponível através da propriedade do ComponentMetaData componente.
Os exemplos de código a seguir mostram um componente que tem uma entrada e duas saídas, incluindo uma saída de erro. O primeiro exemplo mostra como criar uma saída de erro que é síncrona com a entrada. O segundo exemplo mostra como criar uma saída de erro que é assíncrona.
public override void ProvideComponentProperties()
{
// Specify that the component has an error output.
ComponentMetaData.UsesDispositions = true;
// Create the input.
IDTSInput100 input = ComponentMetaData.InputCollection.New();
input.Name = "Input";
input.ErrorRowDisposition = DTSRowDisposition.RD_NotUsed;
input.ErrorOrTruncationOperation = "A string describing the possible error or truncation that may occur during execution.";
// Create the default output.
IDTSOutput100 output = ComponentMetaData.OutputCollection.New();
output.Name = "Output";
output.SynchronousInputID = input.ID;
output.ExclusionGroup = 1;
// Create the error output.
IDTSOutput100 errorOutput = ComponentMetaData.OutputCollection.New();
errorOutput.IsErrorOut = true;
errorOutput.Name = "ErrorOutput";
errorOutput.SynchronousInputID = input.ID;
errorOutput.ExclusionGroup = 1;
}
Public Overrides Sub ProvideComponentProperties()
' Specify that the component has an error output.
ComponentMetaData.UsesDispositions = True
Dim input As IDTSInput100 = ComponentMetaData.InputCollection.New
' Create the input.
input.Name = "Input"
input.ErrorRowDisposition = DTSRowDisposition.RD_NotUsed
input.ErrorOrTruncationOperation = "A string describing the possible error or truncation that may occur during execution."
' Create the default output.
Dim output As IDTSOutput100 = ComponentMetaData.OutputCollection.New
output.Name = "Output"
output.SynchronousInputID = input.ID
output.ExclusionGroup = 1
' Create the error output.
Dim errorOutput As IDTSOutput100 = ComponentMetaData.OutputCollection.New
errorOutput.IsErrorOut = True
errorOutput.Name = "ErrorOutput"
errorOutput.SynchronousInputID = input.ID
errorOutput.ExclusionGroup = 1
End Sub
O exemplo de código a seguir cria uma saída de erro que é assíncrona.
public override void ProvideComponentProperties()
{
// Specify that the component has an error output.
ComponentMetaData.UsesDispositions = true;
// Create the input.
IDTSInput100 input = ComponentMetaData.InputCollection.New();
input.Name = "Input";
input.ErrorRowDisposition = DTSRowDisposition.RD_NotUsed;
input.ErrorOrTruncationOperation = "A string describing the possible error or truncation that may occur during execution.";
// Create the default output.
IDTSOutput100 output = ComponentMetaData.OutputCollection.New();
output.Name = "Output";
// Create the error output.
IDTSOutput100 errorOutput = ComponentMetaData.OutputCollection.New();
errorOutput.Name = "ErrorOutput";
errorOutput.IsErrorOut = true;
}
Public Overrides Sub ProvideComponentProperties()
' Specify that the component has an error output.
ComponentMetaData.UsesDispositions = True
' Create the input.
Dim input As IDTSInput100 = ComponentMetaData.InputCollection.New
' Create the default output.
input.Name = "Input"
input.ErrorRowDisposition = DTSRowDisposition.RD_NotUsed
input.ErrorOrTruncationOperation = "A string describing the possible error or truncation that may occur during execution."
' Create the error output.
Dim output As IDTSOutput100 = ComponentMetaData.OutputCollection.New
output.Name = "Output"
Dim errorOutput As IDTSOutput100 = ComponentMetaData.OutputCollection.New
errorOutput.Name = "ErrorOutput"
errorOutput.IsErrorOut = True
End Sub
Redirecionar uma linha para uma saída de erro
Depois de adicionar uma saída de erro a um componente, você deve fornecer código que manipule as condições de erro ou truncamento específicas do componente e redirecione as linhas de erro ou truncamento para a saída de erro. Você pode fazer isso de duas maneiras, dependendo se a saída do erro é síncrona ou assíncrona.
Redirecionar uma linha com saídas síncronas
As linhas são enviadas para saídas síncronas chamando o DirectErrorRowPipelineBuffer método da classe. A chamada de método inclui como parâmetros a ID da saída de erro, o código de erro definido pelo componente e o índice da coluna que o componente não pôde processar.
O exemplo de código a seguir demonstra como direcionar uma linha em um buffer para uma saída de erro síncrona usando o DirectErrorRow método.
public override void ProcessInput(int inputID, PipelineBuffer buffer)
{
IDTSInput100 input = ComponentMetaData.InputCollection.GetObjectByID(inputID);
// This code sample assumes the component has two outputs, one the default,
// the other the error output. If the errorOutputIndex returned from GetErrorOutputInfo
// is 0, then the default output is the second output in the collection.
int defaultOutputID = -1;
int errorOutputID = -1;
int errorOutputIndex = -1;
GetErrorOutputInfo(ref errorOutputID,ref errorOutputIndex);
if (errorOutputIndex == 0)
defaultOutputID = ComponentMetaData.OutputCollection[1].ID;
else
defaultOutputID = ComponentMetaData.OutputCollection[0].ID;
while (buffer.NextRow())
{
try
{
// TODO: Implement code to process the columns in the buffer row.
// Ideally, your code should detect potential exceptions before they occur, rather
// than having a generic try/catch block such as this.
// However, because the error or truncation implementation is specific to each component,
// this sample focuses on actually directing the row, and not a single error or truncation.
// Unless an exception occurs, direct the row to the default
buffer.DirectRow(defaultOutputID);
}
catch
{
// Yes, has the user specified to redirect the row?
if (input.ErrorRowDisposition == DTSRowDisposition.RD_RedirectRow)
{
// Yes, direct the row to the error output.
// TODO: Add code to include the errorColumnIndex.
buffer.DirectErrorRow(errorOutputID, 0, errorColumnIndex);
}
else if (input.ErrorRowDisposition == DTSRowDisposition.RD_FailComponent || input.ErrorRowDisposition == DTSRowDisposition.RD_NotUsed)
{
// No, the user specified to fail the component, or the error row disposition was not set.
throw new Exception("An error occurred, and the DTSRowDisposition is either not set, or is set to fail component.");
}
else
{
// No, the user specified to ignore the failure so
// direct the row to the default output.
buffer.DirectRow(defaultOutputID);
}
}
}
}
Public Overrides Sub ProcessInput(ByVal inputID As Integer, ByVal buffer As PipelineBuffer)
Dim input As IDTSInput100 = ComponentMetaData.InputCollection.GetObjectByID(inputID)
' This code sample assumes the component has two outputs, one the default,
' the other the error output. If the errorOutputIndex returned from GetErrorOutputInfo
' is 0, then the default output is the second output in the collection.
Dim defaultOutputID As Integer = -1
Dim errorOutputID As Integer = -1
Dim errorOutputIndex As Integer = -1
GetErrorOutputInfo(errorOutputID, errorOutputIndex)
If errorOutputIndex = 0 Then
defaultOutputID = ComponentMetaData.OutputCollection(1).ID
Else
defaultOutputID = ComponentMetaData.OutputCollection(0).ID
End If
While buffer.NextRow
Try
' TODO: Implement code to process the columns in the buffer row.
' Ideally, your code should detect potential exceptions before they occur, rather
' than having a generic try/catch block such as this.
' However, because the error or truncation implementation is specific to each component,
' this sample focuses on actually directing the row, and not a single error or truncation.
' Unless an exception occurs, direct the row to the default
buffer.DirectRow(defaultOutputID)
Catch
' Yes, has the user specified to redirect the row?
If input.ErrorRowDisposition = DTSRowDisposition.RD_RedirectRow Then
' Yes, direct the row to the error output.
' TODO: Add code to include the errorColumnIndex.
buffer.DirectErrorRow(errorOutputID, 0, errorColumnIndex)
Else
If input.ErrorRowDisposition = DTSRowDisposition.RD_FailComponent OrElse input.ErrorRowDisposition = DTSRowDisposition.RD_NotUsed Then
' No, the user specified to fail the component, or the error row disposition was not set.
Throw New Exception("An error occurred, and the DTSRowDisposition is either not set, or is set to fail component.")
Else
' No, the user specified to ignore the failure so
' direct the row to the default output.
buffer.DirectRow(defaultOutputID)
End If
End If
End Try
End While
End Sub
Redirecionar uma linha com saídas assíncronas
Em vez de direcionar linhas para uma saída, como é feito com saídas de erro síncronas, os componentes com saídas assíncronas enviam uma linha para uma saída de erro adicionando explicitamente uma linha à saída PipelineBuffer. A implementação de um componente que usa saídas de erro assíncronas requer a adição de colunas à saída de erro que são fornecidas aos componentes downstream e o armazenamento em cache do buffer de saída para a saída de erro fornecida ao componente durante o PrimeOutput método. Os detalhes da implementação de um componente com saídas assíncronas são abordados em detalhes no tópico Desenvolvendo um componente de transformação personalizado com saídas assíncronas. Se as colunas não forem explicitamente adicionadas à saída de erro, a linha de buffer adicionada ao buffer de saída conterá apenas as duas colunas de erro.
Para enviar uma linha para uma saída de erro assíncrona, você deve adicionar uma linha ao buffer de saída de erro. Às vezes, uma linha pode já ter sido adicionada ao buffer de saída sem erro e você deve remover essa linha usando o RemoveRow método. Em seguida, você define os valores das colunas de buffer de saída e, finalmente, chama o SetErrorInfo método para fornecer o código de erro específico do componente e o valor da coluna de erro.
O exemplo a seguir demonstra como usar uma saída de erro para um componente com saídas assíncronas. Quando o erro simulado ocorre, o componente adiciona uma linha ao buffer de saída de erro, copia os valores que foram adicionados anteriormente ao buffer de saída sem erro para o buffer de saída de erro, remove a linha que foi adicionada ao buffer de saída sem erro e, finalmente, define o código de erro e os valores da coluna de erro chamando o SetErrorInfo método.
int []columnIndex;
int errorOutputID = -1;
int errorOutputIndex = -1;
public override void PreExecute()
{
IDTSOutput100 defaultOutput = null;
this.GetErrorOutputInfo(ref errorOutputID, ref errorOutputIndex);
foreach (IDTSOutput100 output in ComponentMetaData.OutputCollection)
{
if (output.ID != errorOutputID)
defaultOutput = output;
}
columnIndex = new int[defaultOutput.OutputColumnCollection.Count];
for(int col =0 ; col < defaultOutput.OutputColumnCollection.Count; col++)
{
IDTSOutputColumn100 column = defaultOutput.OutputColumnCollection[col];
columnIndex[col] = BufferManager.FindColumnByLineageID(defaultOutput.Buffer, column.LineageID);
}
}
public override void PrimeOutput(int outputs, int[] outputIDs, PipelineBuffer[] buffers)
{
for( int x=0; x < outputs; x++ )
{
if (outputIDs[x] == errorOutputID)
this.errorBuffer = buffers[x];
else
this.defaultBuffer = buffers[x];
}
int rows = 100;
Random random = new Random(System.DateTime.Now.Millisecond);
for (int row = 0; row < rows; row++)
{
try
{
defaultBuffer.AddRow();
for (int x = 0; x < columnIndex.Length; x++)
defaultBuffer[columnIndex[x]] = random.Next();
// Simulate an error.
if ((row % 2) == 0)
throw new Exception("A simulated error.");
}
catch
{
// Add a row to the error buffer.
errorBuffer.AddRow();
// Get the values from the default buffer
// and copy them to the error buffer.
for (int x = 0; x < columnIndex.Length; x++)
errorBuffer[columnIndex[x]] = defaultBuffer[columnIndex[x]];
// Set the error information.
errorBuffer.SetErrorInfo(errorOutputID, 1, 0);
// Remove the row that was added to the default buffer.
defaultBuffer.RemoveRow();
}
}
if (defaultBuffer != null)
defaultBuffer.SetEndOfRowset();
if (errorBuffer != null)
errorBuffer.SetEndOfRowset();
}
Private columnIndex As Integer()
Private errorOutputID As Integer = -1
Private errorOutputIndex As Integer = -1
Public Overrides Sub PreExecute()
Dim defaultOutput As IDTSOutput100 = Nothing
Me.GetErrorOutputInfo(errorOutputID, errorOutputIndex)
For Each output As IDTSOutput100 In ComponentMetaData.OutputCollection
If Not (output.ID = errorOutputID) Then
defaultOutput = output
End If
Next
columnIndex = New Integer(defaultOutput.OutputColumnCollection.Count) {}
Dim col As Integer = 0
While col < defaultOutput.OutputColumnCollection.Count
Dim column As IDTSOutputColumn100 = defaultOutput.OutputColumnCollection(col)
columnIndex(col) = BufferManager.FindColumnByLineageID(defaultOutput.Buffer, column.LineageID)
System.Math.Min(System.Threading.Interlocked.Increment(col),col-1)
End While
End Sub
Public Overrides Sub PrimeOutput(ByVal outputs As Integer, ByVal outputIDs As Integer(), ByVal buffers As PipelineBuffer())
Dim x As Integer = 0
While x < outputs
If outputIDs(x) = errorOutputID Then
Me.errorBuffer = buffers(x)
Else
Me.defaultBuffer = buffers(x)
End If
System.Math.Min(System.Threading.Interlocked.Increment(x),x-1)
End While
Dim rows As Integer = 100
Dim random As Random = New Random(System.DateTime.Now.Millisecond)
Dim row As Integer = 0
While row < rows
Try
defaultBuffer.AddRow
Dim x As Integer = 0
While x < columnIndex.Length
defaultBuffer(columnIndex(x)) = random.Next
System.Math.Min(System.Threading.Interlocked.Increment(x),x-1)
End While
' Simulate an error.
If (row Mod 2) = 0 Then
Throw New Exception("A simulated error.")
End If
Catch
' Add a row to the error buffer.
errorBuffer.AddRow
' Get the values from the default buffer
' and copy them to the error buffer.
Dim x As Integer = 0
While x < columnIndex.Length
errorBuffer(columnIndex(x)) = defaultBuffer(columnIndex(x))
System.Math.Min(System.Threading.Interlocked.Increment(x),x-1)
End While
' Set the error information.
errorBuffer.SetErrorInfo(errorOutputID, 1, 0)
' Remove the row that was added to the default buffer.
defaultBuffer.RemoveRow
End Try
System.Math.Min(System.Threading.Interlocked.Increment(row),row-1)
End While
If Not (defaultBuffer Is Nothing) Then
defaultBuffer.SetEndOfRowset
End If
If Not (errorBuffer Is Nothing) Then
errorBuffer.SetEndOfRowset
End If
End Sub