Sviluppo di un componente di trasformazione personalizzato con output sincroniDeveloping a Custom Transformation Component with Synchronous Outputs

I componenti di trasformazione con output sincroni ricevono righe dai componenti a monte, quindi leggono o modificano i valori nelle colonne di queste righe mentre le passano ai componenti a valle.Transformation components with synchronous outputs receive rows from upstream components, and read or modify the values in the columns of these rows as they pass the rows to downstream components. Possono anche definire colonne di output aggiuntive derivate dalle colonne fornite dai componenti a monte, ma non aggiungono righe al flusso di dati.They may also define additional output columns that are derived from the columns provided by upstream components, but they do not add rows to the data flow. Per ulteriori informazioni sulla differenza tra componenti sincroni e asincroni, vedere comprensione sincrona e asincrona trasformazioni.For more information about the difference between synchronous and asynchronous components, see Understanding Synchronous and Asynchronous Transformations.

Questo tipo di componente è indicato per attività in cui i dati vengono modificati in linea quando vengono forniti al componente e in cui il componente non deve necessariamente vedere tutte le righe prima di elaborarle.This kind of component is suited for tasks where the data is modified inline as it is provided to the component and where the component does not have to see all the rows before processing them. Si tratta del componente più facile da sviluppare, perché le trasformazioni con output sincroni solitamente non si connettono a origini dati esterne, non gestiscono colonne di metadati esterne né aggiungono righe ai buffer di output.It is the easiest component to develop because transformations with synchronous outputs typically do not connect to external data sources, manage external metadata columns, or add rows to output buffers.

La creazione di un componente di trasformazione con output sincroni richiede l'aggiunta di un oggetto IDTSInput100 che conterrà le colonne a monte selezionate per il componente e di un oggetto IDTSOutput100 che può contenere colonne derivate create dal componente.Creating a transformation component with synchronous outputs involves adding an IDTSInput100 that will contain the upstream columns selected for the component, and a IDTSOutput100 object that may contain derived columns created by the component. Include anche l'implementazione dei metodi della fase di progettazione e la specifica di codice che legge o modifica le colonne nelle righe del buffer in ingresso durante l'esecuzione.It also includes implementing the design-time methods, and providing code that reads or modifies the columns in the incoming buffer rows during execution.

In questa sezione vengono fornite le informazioni necessarie per implementare un componente di trasformazione personalizzato, con esempi di codice che consentono di comprenderne meglio i concetti.This section provides the information that is required to implement a custom transformation component, and provides code examples to help you better understand the concepts.

Fase di progettazioneDesign Time

Il codice della fase di progettazione per questo componente richiede la creazione degli input e degli output, l'aggiunta di eventuali colonne di output aggiuntive generate dal componente e la convalida della configurazione del componente.The design-time code for this component involves creating the inputs and outputs, adding any additional output columns that the component generates, and validating the configuration of the component.

Creazione del componenteCreating the Component

Gli input, gli output e le proprietà personalizzate del componente vengono in genere creati durante il metodo ProvideComponentProperties.The inputs, outputs, and custom properties of the component are typically created during the ProvideComponentProperties method. Sono disponibili due modi per aggiungere l'input e l'output di un componente di trasformazione con output sincroni.There are two ways that you can add the input and the output of a transformation component with synchronous outputs. È possibile utilizzare l'implementazione della classe di base del metodo e quindi modificare l'input e output predefiniti creati oppure aggiungere manualmente l'input e l'output in modo esplicito.You can use the base class implementation of the method and then modify the default input and output that it creates, or you can explicitly add the input and output yourself.

Nell'esempio di codice seguente è illustrata un'implementazione di ProvideComponentProperties che aggiunge in modo esplicito gli oggetti di input e di output.The following code example shows an implementation of ProvideComponentProperties that explicitly adds the input and output objects. In un commento è inclusa la chiamata alla classe di base che consente di ottenere lo stesso risultato.The call to the base class that would accomplish the same thing is included in a comment.

using Microsoft.SqlServer.Dts.Pipeline;  
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;  
using Microsoft.SqlServer.Dts.Runtime;  

namespace Microsoft.Samples.SqlServer.Dts  
{  
    [DtsPipelineComponent(DisplayName = "SynchronousComponent", ComponentType = ComponentType.Transform)]  
    public class SyncComponent : PipelineComponent  
    {  

        public override void ProvideComponentProperties()  
        {  
            // Add the input.  
            IDTSInput100 input = ComponentMetaData.InputCollection.New();  
            input.Name = "Input";  

            // Add the output.  
            IDTSOutput100 output = ComponentMetaData.OutputCollection.New();  
            output.Name = "Output";  
            output.SynchronousInputID = input.ID;  

            // Alternatively, you can let the base class add the input and output  
            // and set the SynchronousInputID of the output to the ID of the input.  
            // base.ProvideComponentProperties();  
        }  
    }  
}  
Imports Microsoft.SqlServer.Dts.Pipeline  
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper  
Imports Microsoft.SqlServer.Dts.Runtime  

<DtsPipelineComponent(DisplayName:="SynchronousComponent", ComponentType:=ComponentType.Transform)> _  
Public Class SyncComponent  
    Inherits PipelineComponent  

    Public Overrides Sub ProvideComponentProperties()  

        ' Add the input.  
        Dim input As IDTSInput100 = ComponentMetaData.InputCollection.New()  
        input.Name = "Input"  

        ' Add the output.  
        Dim output As IDTSOutput100 = ComponentMetaData.OutputCollection.New()  
        output.Name = "Output"  
        output.SynchronousInputID = Input.ID  

        ' Alternatively, you can let the base class add the input and output  
        ' and set the SynchronousInputID of the output to the ID of the input.  
        ' base.ProvideComponentProperties();  

    End Sub  

End Class  

Creazione e configurazione di colonne di outputCreating and Configuring Output Columns

Anche se i componenti di trasformazione con output sincroni non aggiungono righe ai buffer, possono aggiungere colonne di output aggiuntive all'output.Although transformation components with synchronous outputs do not add rows to buffers, they may add extra output columns to their output. In genere, quando un componente aggiunge una colonna di output, i relativi valori vengono derivati in fase di esecuzione dai dati contenuti in una o più colonne fornite al componente da un componente a monte.Typically, when a component adds an output column, the values for the new output column are derived at run time from the data that is contained in one or more of the columns provided to the component by an upstream component.

Dopo la creazione di una colonna di output, è necessario impostare le relative proprietà del tipo di dati.After an output column has been created, its data type properties must be set. L'impostazione delle proprietà del tipo di dati di una colonna di output richiede una gestione speciale e viene eseguita chiamando il metodo SetDataTypeProperties.Setting the data type properties of an output column requires special handling and is performed by calling the SetDataTypeProperties method. Questo metodo è necessario perché le proprietà DataType, Length, Precision e CodePage sono singolarmente di sola lettura, in quanto ognuna dipende dalle impostazioni dell'altra.This method is required because the DataType, Length, Precision, and CodePage properties are individually read-only, because each depends on the settings of the other. Questo metodo garantisce che i valori delle proprietà siano impostati in modo coerente e l'attività Flusso di dati verifica se sono stati impostati correttamente.This method guarantees that the values of the properties are set consistently, and the data flow task validates that they are set correctly.

L'oggetto DataType della colonna determina i valori impostati per le altre proprietà.The DataType of the column determines the values that are set for the other properties. Nella tabella seguente sono illustrati i requisiti delle proprietà dipendenti per ogni oggetto DataType.The following table shows the requirements on the dependent properties for each DataType. Le proprietà dipendenti dei tipi di dati non elencati sono impostate su zero.The data types not listed have their dependent properties set to zero.

DataTypeDataType LunghezzaLength ScalaScale PrecisionePrecision CodePageCodePage
DT_DECIMALDT_DECIMAL 00 Maggiore di 0 e minore o uguale a 28.Greater than 0 and less than or equal to 28. 00 00
DT_CYDT_CY 00 00 00 00
DT_NUMERICDT_NUMERIC 00 Maggiore di 0 e minore o uguale a 28, nonché minore di Precision.Greater than 0 and less than or equal to 28, and less than Precision. Maggiore o uguale a 1 e minore o uguale a 38.Greater than or equal to 1 and less than or equal to 38. 00
DT_BYTESDT_BYTES Maggiore di 0.Greater than 0. 00 00 00
DT_STRDT_STR Maggiore di 0 e minore di 8000.Greater than 0 and less than 8000. 00 00 Diverso da 0 e tabella codici valida.Not 0, and a valid code page.
DT_WSTRDT_WSTR Maggiore di 0 e minore di 4000.Greater than 0 and less than 4000. 00 00 00

Poiché le restrizioni sulle proprietà del tipo di dati sono basate sul tipo di dati della colonna di output, è necessario scegliere il tipo di dati di Integration ServicesIntegration Services corretto quando si utilizzano tipi gestiti.Because the restrictions on the data type properties are based on the data type of the output column, you must choose the correct Integration ServicesIntegration Services data type when you work with managed types. La classe di base fornisce tre metodi di supporto, ConvertBufferDataTypeToFitManaged, BufferTypeToDataRecordType e DataRecordTypeToBufferType, per assistere gli sviluppatori di componenti gestiti nella selezione di un tipo di dati di SSISSSIS dato un tipo gestito.The base class provides three helper methods, ConvertBufferDataTypeToFitManaged, BufferTypeToDataRecordType, and DataRecordTypeToBufferType that assist managed component developers in selecting an SSISSSIS data type given a managed type. Questi metodi convertono i tipi di dati gestiti nei tipi di dati di SSISSSIS e viceversa.These methods convert managed data types to SSISSSIS data types, and vice versa.

Fase di esecuzioneRun Time

Generalmente, l'implementazione della parte runtime del componente è suddivisa in due attività: individuazione delle colonne di input e output del componente nel buffer e lettura o scrittura dei valori di tali colonne nelle righe del buffer in ingresso.Generally, the implementation of the run-time part of the component is categorized into two tasks—locating the input and output columns of the component in the buffer, and reading or writing the values of these columns in the incoming buffer rows.

Individuazione di colonne nel bufferLocating Columns in the Buffer

Il numero di colonne nei buffer forniti a un componente durante l'esecuzione supera in genere il numero di colonne presenti nelle raccolte di input o output del componente,The number of columns in the buffers that are provided to a component during execution will likely exceed the number of columns in the input or output collections of the component. perché ogni buffer contiene tutte le colonne di output definite nei componenti in un flusso di dati.This is because each buffer contains all the output columns defined in the components in a data flow. Per assicurarsi che le colonne del buffer corrispondano correttamente alle colonne dell'input o dell'output, gli sviluppatori di componenti devono utilizzare il metodo FindColumnByLineageID di BufferManager.To ensure that the buffer columns are correctly matched to the columns of the input or output, component developers must use the FindColumnByLineageID method of the BufferManager. Questo metodo individua una colonna nel buffer specificato in base al relativo ID di derivazione.This method locates a column in the specified buffer by its lineage ID. In genere, le colonne vengono individuate durante PreExecute perché si tratta del primo metodo di runtime in cui la proprietà BufferManager diventa disponibile.Typically columns are located during PreExecute because this is the first run-time method where the BufferManager property becomes available.

Nell'esempio di codice seguente è illustrato un componente che individua gli indici delle colonne nella propria raccolta di colonne di input e output durante PreExecute.The following code example shows a component that locates indexes of the columns in its input and output column collection during PreExecute. Gli indici delle colonne vengono archiviati in una matrice di valori integer e il componente può accedervi durante ProcessInput.The column indexes are stored in an integer array, and can be accessed by the component during ProcessInput.

int []inputColumns;  
int []outputColumns;  

public override void PreExecute()  
{  
    IDTSInput100 input = ComponentMetaData.InputCollection[0];  
    IDTSOutput100 output = ComponentMetaData.OutputCollection[0];  

    inputColumns = new int[input.InputColumnCollection.Count];  
    outputColumns = new int[output.OutputColumnCollection.Count];  

    for(int col=0; col < input.InputColumnCollection.Count; col++)  
    {  
        IDTSInputColumn100 inputColumn = input.InputColumnCollection[col];  
        inputColumns[col] = BufferManager.FindColumnByLineageID(input.Buffer, inputColumn.LineageID);  
    }  

    for(int col=0; col < output.OutputColumnCollection.Count; col++)  
    {  
        IDTSOutputColumn100 outputColumn = output.OutputColumnCollection[col];  
        outputColumns[col] = BufferManager.FindColumnByLineageID(input.Buffer, outputColumn.LineageID);  
    }  

}  
Public Overrides Sub PreExecute()  

    Dim input As IDTSInput100 = ComponentMetaData.InputCollection(0)  
    Dim output As IDTSOutput100 = ComponentMetaData.OutputCollection(0)  

    ReDim inputColumns(input.InputColumnCollection.Count)  
    ReDim outputColumns(output.OutputColumnCollection.Count)  

    For col As Integer = 0 To input.InputColumnCollection.Count  

        Dim inputColumn As IDTSInputColumn100 = input.InputColumnCollection(col)  
        inputColumns(col) = BufferManager.FindColumnByLineageID(input.Buffer, inputColumn.LineageID)  
    Next  

    For col As Integer = 0 To output.OutputColumnCollection.Count  

        Dim outputColumn As IDTSOutputColumn100 = output.OutputColumnCollection(col)  
        outputColumns(col) = BufferManager.FindColumnByLineageID(input.Buffer, outputColumn.LineageID)  
    Next  

End Sub  

Elaborazione di righeProcessing Rows

I componenti ricevono oggetti PipelineBuffer che contengono righe e colonne nel metodo ProcessInput.Components receive PipelineBuffer objects that contain rows and columns in the ProcessInput method. Durante questo metodo vengono scorse le righe nel buffer e vengono lette e modificate le colonne identificate durante PreExecute .During this method the rows in the buffer are iterated, and the columns identified during PreExecute are read and modified. Il metodo viene chiamato ripetutamente dall'attività Flusso di dati finché non vengono più fornite righe dal componente a monte.The method is called repeatedly by the data flow task until no more rows are provided from the upstream component.

Una singola colonna nel buffer viene letta o scritta utilizzando il metodo di accesso dell'indicizzatore di matrice oppure utilizzando uno del ottenere o impostare metodi.An individual column in the buffer is read or written by using the array indexer access method, or by using one of the Get or Set methods. Il ottenere e impostare metodi sono più efficienti e deve essere utilizzati quando è noto il tipo di dati della colonna nel buffer.The Get and Set methods are more efficient and should be used when the data type of the column in the buffer is known.

Nell'esempio di codice seguente è illustrata un'implementazione del metodo ProcessInput che elabora le righe in ingresso.The following code example shows an implementation of the ProcessInput method that processes incoming rows.

public override void ProcessInput( int InputID, PipelineBuffer buffer)  
{  
       while( buffer.NextRow())  
       {  
            for(int x=0; x < inputColumns.Length;x++)  
            {  
                if(!buffer.IsNull(inputColumns[x]))  
                {  
                    object columnData = buffer[inputColumns[x]];  
                    // TODO: Modify the column data.  
                    buffer[inputColumns[x]] = columnData;  
                }  
            }  

      }  
}  
Public Overrides Sub ProcessInput(ByVal InputID As Integer, ByVal buffer As PipelineBuffer)  

        While (buffer.NextRow())  

            For x As Integer = 0 To inputColumns.Length  

                if buffer.IsNull(inputColumns(x)) = false then  

                    Dim columnData As Object = buffer(inputColumns(x))  
                    ' TODO: Modify the column data.  
                    buffer(inputColumns(x)) = columnData  

                End If  
            Next  

        End While  
End Sub  

EsempioSample

Nell'esempio seguente è illustrato un componente di trasformazione semplice con output sincroni che converte i valori di tutte le colonne di tipo stringa in lettere maiuscole.The following sample shows a simple transformation component with synchronous outputs that converts the values of all string columns to uppercase. Nell'esempio non vengono dimostrati tutti i metodi e le funzionalità descritti nell'argomento.This sample does not demonstrate all the methods and functionality discussed in this topic. Vengono descritti i metodi importanti di cui ogni componente di trasformazione personalizzato con output sincroni deve eseguire l'override, ma non è incluso codice per la convalida in fase di progettazione.It demonstrates the important methods that every custom transformation component with synchronous outputs must override, but does not contain code for design-time validation.

using System;  
using System.Collections;  
using Microsoft.SqlServer.Dts.Pipeline;  
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;  
using Microsoft.SqlServer.Dts.Runtime.Wrapper;  

namespace Uppercase  
{  
  [DtsPipelineComponent(DisplayName = "Uppercase")]  
  public class Uppercase : PipelineComponent  
  {  
    ArrayList m_ColumnIndexList = new ArrayList();  

    public override void ProvideComponentProperties()  
    {  
      base.ProvideComponentProperties();  
      ComponentMetaData.InputCollection[0].Name = "Uppercase Input";  
      ComponentMetaData.OutputCollection[0].Name = "Uppercase Output";  
    }  

    public override void PreExecute()  
    {  
      IDTSInput100 input = ComponentMetaData.InputCollection[0];  
      IDTSInputColumnCollection100 inputColumns = input.InputColumnCollection;  

      foreach (IDTSInputColumn100 column in inputColumns)  
      {  
        if (column.DataType == DataType.DT_STR || column.DataType == DataType.DT_WSTR)  
        {  
          m_ColumnIndexList.Add((int)BufferManager.FindColumnByLineageID(input.Buffer, column.LineageID));  
        }  
      }  
    }  

    public override void ProcessInput(int inputID, PipelineBuffer buffer)  
    {  
      while (buffer.NextRow())  
      {  
        foreach (int columnIndex in m_ColumnIndexList)  
        {  
          string str = buffer.GetString(columnIndex);  
          buffer.SetString(columnIndex, str.ToUpper());  
        }  
      }  
    }  
  }  
}  
Imports System   
Imports System.Collections   
Imports Microsoft.SqlServer.Dts.Pipeline   
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper   
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper   
Namespace Uppercase   

 <DtsPipelineComponent(DisplayName="Uppercase")> _   
 Public Class Uppercase   
 Inherits PipelineComponent   
   Private m_ColumnIndexList As ArrayList = New ArrayList   

   Public  Overrides Sub ProvideComponentProperties()   
     MyBase.ProvideComponentProperties   
     ComponentMetaData.InputCollection(0).Name = "Uppercase Input"   
     ComponentMetaData.OutputCollection(0).Name = "Uppercase Output"   
   End Sub   

   Public  Overrides Sub PreExecute()   
     Dim input As IDTSInput100 = ComponentMetaData.InputCollection(0)   
     Dim inputColumns As IDTSInputColumnCollection100 = input.InputColumnCollection   
     For Each column As IDTSInputColumn100 In inputColumns   
       If column.DataType = DataType.DT_STR OrElse column.DataType = DataType.DT_WSTR Then   
         m_ColumnIndexList.Add(CType(BufferManager.FindColumnByLineageID(input.Buffer, column.LineageID), Integer))   
       End If   
     Next   
   End Sub   

   Public  Overrides Sub ProcessInput(ByVal inputID As Integer, ByVal buffer As PipelineBuffer)   
     While buffer.NextRow   
       For Each columnIndex As Integer In m_ColumnIndexList   
         Dim str As String = buffer.GetString(columnIndex)   
         buffer.SetString(columnIndex, str.ToUpper)   
       Next   
     End While   
   End Sub   
 End Class   
End Namespace  

Vedere ancheSee Also

Sviluppo di un componente di trasformazione personalizzato con output asincroni Developing a Custom Transformation Component with Asynchronous Outputs
Informazioni sulle trasformazioni sincrone e asincrone Understanding Synchronous and Asynchronous Transformations
Creazione di una trasformazione sincrona con il componente ScriptCreating a Synchronous Transformation with the Script Component