Renaud Harduin
Développement de composant Integration Services (SSIS)
Par Renaud Harduin publié le 08/01/2006 à 14:16, lu 8451 fois, 6 pages
 4 | 4 - Implémentation de la logique de transformation
Téléchargez le code source - 263 Kb
4 - Implémentation de la logique de transformation
4.1 – PreExecute
Comme son nom l'indique PreExecute est appelée avant les appels à la méthode ProcessInput. C'est ici notamment que l'on va créer le fichier cible. L'accès à la valeur de Filename se faire par ComponentMetadat.CustomPropertyCollection.
Pour générer le xml, nous utiliserons la classe XmlWriter en alimentant les tags de base.
public override void PreExecute()
  {
   // STEP 1=
   // Destination file management

   /* 1.1: gets the filename, test if the file exist (and delete it )*/
   this.FileName = this.ComponentMetaData.CustomPropertyCollection[Const_FileName_AttributeName].Value.ToString();
   if (System.IO.File.Exists(this.FileName))
   {
    System.IO.File.Delete(this.FileName);
   }

   /*1.2: Creates the XmlWriter */
   XmlWriterSettings xmlSettings = new XmlWriterSettings();
   xmlSettings.Encoding = Encoding.UTF8;
   xmlSettings.Indent = true;
   this.Xml = XmlWriter.Create(this.FileName, xmlSettings);
   
   /*1.3: Writes the initial headers */
   Xml.WriteStartDocument(true);
   Xml.WriteStartElement(_Xml_RootTag);
   base.PreExecute();



   // STEP 2=
   // Gathers information on columns and place it into a ColumnInformation Array
   IDTSInput90 input = ComponentMetaData.InputCollection[0];
   colInfos = new ColumnInformation[input.InputColumnCollection.Count];

   for (int i = 0; i < input.InputColumnCollection.Count; i++)
   {
    ColumnInformation colInfo = new ColumnInformation();
    colInfo.ColumnName = input.InputColumnCollection[i].Name;
    colInfo.BufferIndex = BufferManager.FindColumnByLineageID(input.Buffer, input.InputColumnCollection[i].LineageID);
    colInfo.DataType = input.InputColumnCollection[i].DataType;
    colInfos[i] = colInfo;
   }
  }
Dans un second temps, nous recherchons dans l'Input la liste des colonnes afin de charger un tableau de ColumnInformation pour mettre en “cache” l'information (classe de la solution dont je vous donne le code ci dessous) :
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[assembly: CLSCompliant(false)]
namespace BILab.Technical.BI.ETL.Pipeline.Common
{
 public class ColumnInformation
 {
  private int _bufferIndex;

  public int BufferIndex
  {
   get { return _bufferIndex; }
   set { _bufferIndex = value; }
  }

  private string columnName;

  public string ColumnName
  {
   get { return columnName; }
   set { columnName = value; }
  }

  private DataType _dataType;

  public DataType DataType
  {
    get { return _dataType; }
    set { _dataType = value; }
  }
 }
}
L'accès au détail des métadonnées sur le type et la position des colonnes dans le buffer de donnée (PipelineBuffer) à l'exécution se fait au travers d'un objet BufferManager (type IDTSBufferManager90).
En effet, le mécanisme du PipelineBuffer SSIS nous “impose” de retrouver la colonne non pas par son nom mais par un index (dans la mesure où on peut avoir plus de colonne dans le pipelinebuffer à l'exécution que définie dans input).

Nous sauvegardons cet index dans une propriété Index et son identification se fait par l'appel de la méthode :
int FindColumnByLineageID (
 int hBufferType, /* Id du buffer concern, ici input.Buffer */
 int nLineageID /* clef/id de la colonne  identifer */
)
Nous créons donc un tableau de ColumnInformation plus “simple” à parcourir lors du traitement.
4.2 – ProcessInput
  public override void ProcessInput(int inputID, PipelineBuffer buffer)
  {
   int colIt;
   string text;
   string columnName ="";
   int retain = -1;
   Type[] types = new Type[0]; ;

   if (buffer.EndOfRowset == false)
   {
    try
    {
     while (buffer.NextRow())
     {
      this.Xml.WriteStartElement(_Xml_RowTag);
       if (!buffer.IsNull(colInfos[colIt].BufferIndex))
       {
        text = buffer[colInfos[colIt].BufferIndex].ToString();
       }
       else
       {
        text = "";
       }
       columnName = colInfos[colIt].ColumnName;
       this.Xml.WriteElementString(columnName, text);

       retain = colIt;
       //this.Xml.WriteStartElement(colInfos[colIt].ColumnName);
       //this.Xml.WriteEndElement();
      }
      this.Xml.WriteEndElement();
      LineCounter++;
     }
    }
    catch (System.Exception ex)
    {
     bool cancel = false;
     StringBuilder sb = new StringBuilder();
     sb.Append("Caught Exception : ");
     sb.Append(ex.Message);
     sb.Append(" - iteration : ");
     sb.Append(retain);
     sb.Append(" - Nb of columns : ");
     sb.Append(colInfos.Length);

     ComponentMetaData.FireError(0, ComponentMetaData.Name, sb.ToString(), string.Empty, 0, out cancel);
     throw new ApplicationException(Resource.CouldNotProcessInput);
     
    }
   }
  }
Cette méthode est appelée pour chaque ligne de chaque Input de notre composant, au cours de laquelle on itère pour chaque ligne envoyée dans le buffer via buffer.NextRow (attendu que nous pouvons recevoir des données de manière asynchrone). Nous alimentons un compeur pour compter le nombre de lignes exportées.

Pour chaque ligne on génère un TAG datarow (paramétrable dans nos propriété, je le rappelle) et nous itérons ensuite dans notre tableau de ColumnInfo pour écrire pour chaque colonne un tag portant le nom de la colonne et ayant comme élément la valeur de la colonne.

Sur ce point nous accédons au contenu de la colonne en allant chercher les donnée dans le buffer par buffer[colInfos[colIt].BufferIndex].
4.3 – PostExecute
Cette méthode finalise le traitement et ferme la destination xml.
public override void PostExecute()
  {
   if ((bool)this.ComponentMetaData.CustomPropertyCollection[Const_OutputNbOfRows_AttributeName].Value)
   {
    Xml.WriteElementString(_Xml_NbOfRowsTag, Convert.ToString(this.LineCounter));
    Xml.WriteEndElement();
   }   
   Xml.WriteEndDocument();
   Xml.Close();
   base.PostExecute();
  }
 
» Démarrer une discussion
 
Discussion démarée par dystopy le 18/07/2007 à 10:52, 2 commentaire(s).