Renaud Harduin
Développement de composant Integration Services (SSIS)
Par Renaud Harduin publié le 08/01/2006 à 14:16, lu 7137 fois, 6 pages
 3 | 3 - Implémentation des propriétés
Téléchargez le code source - 263 Kb
3 - Implémentation des propriétés
3.1 - Surcharge de ProvideComponentProperties
Nous devons donc surcharger un certain nombre de méthodes. La première à traiter est la méthode ProvideComponentProperties

Il s'agit de définir dans cette méthode toutes les Custom Properties du composant. Cette méthode est appelée lorsque vous posez votre composant sur le Control Flow et fige désormais la structure ce cet objet. (Toute nouvelle propriété ne sera pas « réfléchies » et vous obligera à reposer votre composant).

A ce niveau on met en évidence le rôle du ComponentMetadata (de type IDTSComponentMetaData90, Microsoft.SqlServer.Dts.Pipeline.Wrapper Namespace) qui contient toutes les propriétés custom de notre objet, mais bien au delà, la collection des données en Input (InputCollection).

Chacun de ces inputs (de type IDTSInput90) contient la liste des colonnes de l'input dans une collection de InputColumnCollection.
Nous nous reviendrons de ces éléments plus tard.

La première action consiste à appeler (bien entendu) la primitive, et enlever des éventuels objet Output (les symétriques des input dont nous venons de parler) par « base.ComponentMetaData.OutputCollection.RemoveAll(); »
public override void ProvideComponentProperties()
        {
            base.ProvideComponentProperties();
            // Add properties and set the default value;
            base.ComponentMetaData.OutputCollection.RemoveAll();

            // - filename
            IDTSCustomProperty90 filenameProperty = base.ComponentMetaData.CustomPropertyCollection.New();
            filenameProperty.Name = Const_FileName_AttributeName;
            filenameProperty.State = DTSPersistState.PS_PERSISTASCDATA;
            filenameProperty.UITypeEditor = "System.Windows.Forms.Design.FileNameEditor,
                            System.Design, 
                            Version=1.0.3300.0,
                            Culture=neutral,
                            PublicKeyToken=b03f5f7f11d50a3a";
            filenameProperty.Value = "";

            // - Xml Root Tag
            IDTSCustomProperty90 xmlRootProperty = base.ComponentMetaData.CustomPropertyCollection.New();
            xmlRootProperty.Name = Const_XmlRootTag_AttributeName;
            xmlRootProperty.State = DTSPersistState.PS_PERSISTASCDATA;
            xmlRootProperty.Value = "XmlDestination";

            // - Xml Row Tag
            IDTSCustomProperty90 xmlRowProperty = base.ComponentMetaData.CustomPropertyCollection.New();
            xmlRowProperty.Name = Const_XmlRowTag_AttributeName;
            xmlRowProperty.State = DTSPersistState.PS_PERSISTASCDATA;
            xmlRowProperty.Value = "DataRow";

            // - Do we output number of rows into the Xml file
            IDTSCustomProperty90 xmlDoOutputNbOfRows = base.ComponentMetaData.CustomPropertyCollection.New();
            xmlDoOutputNbOfRows.Name = Const_OutputNbOfRows_AttributeName;
            xmlDoOutputNbOfRows.State = DTSPersistState.PS_PERSISTASCDATA;
            xmlDoOutputNbOfRows.Value = true;

            // - Xml Nummber of Row Tag
            IDTSCustomProperty90 xmlNbRowProperty = base.ComponentMetaData.CustomPropertyCollection.New();
            xmlNbRowProperty.Name = Const_XmlNbOfRowsTag_AttributeName;
            xmlNbRowProperty.State = DTSPersistState.PS_PERSISTASCDATA;
            xmlNbRowProperty.Value = "NumberOfRows";
        }
Nous ajoutons ensuite dynamiquement des propriétés Custom en appelant « base.ComponentMetaData.CustomPropertyCollection.New(); ». Cette méthode nous renvoie des IDTSCustomProperty90 sur lequel nous agissons en
  • Attribuant un nom de propriété qui servira de clef
  • Un état pour sa sauvegarde
  • Une valeur de type Object
  • Eventuellement une interface d'édition de la propriété comme pour la propriété filename
Afin de clarifier le code et sa manipulation, nous avons figé les noms de propriété dans des constantes.(cf. prototype de classe).
3.2 - Compilation et déploiement du composant
A ce stade nous avons un composant « droppable » sur le Data Flow, bien que nous n'ayons implémenté aucune logique mais il est intéressant de le déployer pour commencer à le manipuler.
Il vous faudra dans un premier temps signer et déployer votre assembly dans la GAC et copier votre assembly dans « C:\Program Files\microsoft sql server\90\DTS\PipelineComponents ».
Pour cela le plus simple reste encore de définir un « post-build » dans les propriétés de votre projet dans l'onglet « Build Events » :
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /u $(TargetName)
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /i  $(TargetPath)
copy $(TargetPath) "C:\Program Files\Microsoft SQL Server\90\DTS\PipelineComponents"
Démarrez un nouveau Visual Studio, et créez un nouveau package et un nouveau DataFlow.
Cliquez du droit sur la Toolbar et choisissez « Choose Item » :



Dans la boite de dialogue, allez sur l'onglet « SSIS Data Flow Items » et sélectionnez votre assembly.



Votre Composant apparaît dans la Toolbar. Si vous en faites glisser un et que vous invoquez l'éditeur avancés:



Vous retrouvez « Custom Properties » dans l'onglet des propriétés :



Vous pouvez les éditer, fermer votre package et vous retrouverez les éléments que vous avez définis.
3.3 - Surcharge de Validate
Dès lors où l'on rajoute ces Custom Properties, il va falloir les valider afin qu'elles ne corrompent pas le package.
C'est le rôle de la méthode validate qui renvoie un DTSValidationStatus qui peut prendre :
  • VS_BROKEN : pour indiquer que la configuration n'est pas correcte
  • VS_NEEDSNEWMETADATA : le composant est en erreur mais peut être réinitaliser par un appel sur « ReinitializeMetaData »
  • VS_CORRUPT : indique que « this.ComponentMetadata » est corrompu et devra être reconstruit
La méthode Validate est appelée tout au long de l'édition et de la vie du composant.
public override DTSValidationStatus Validate()
  {
bool cancel = false;

this.FileName = this.ComponentMetaData.CustomPropertyCollection[Const_FileName_AttributeName].Value.ToString(); ;
this.Xml_RootTag = (string)this.ComponentMetaData.CustomPropertyCollection[Const_XmlRootTag_AttributeName].Value;
this.Xml_RowTag = (string)this.ComponentMetaData.CustomPropertyCollection[Const_XmlRowTag_AttributeName].Value;
this.DoOutputNumberOfRows = (bool)this.ComponentMetaData.CustomPropertyCollection[Const_OutputNbOfRows_AttributeName].Value;
this.Xml_NbOfRowsTag = (string)this.ComponentMetaData.CustomPropertyCollection[Const_XmlNbOfRowsTag_AttributeName].Value;
   

 DTSValidationStatus status =  base.Validate();
 if( status == DTSValidationStatus.VS_ISVALID)
 {
  if (this.FileName.Length == 0)
  {
   this.ComponentMetaData.FireError(0,ComponentMetaData.Name,Resource.FilenameNotSet,string.Empty,0,out cancel);
   return DTSValidationStatus.VS_ISBROKEN;
  }

  if (this.Xml_RootTag.Length == 0)
  {
   this.ComponentMetaData.FireError(0, ComponentMetaData.Name, Resource.XmlRootTagNotSet, string.Empty, 0, out cancel);
   return DTSValidationStatus.VS_ISBROKEN;
  }

  if (this.Xml_RowTag.Length == 0)
  {
   this.ComponentMetaData.FireError(0, ComponentMetaData.Name, Resource.XmlRowTagNotSet, string.Empty, 0, out cancel);
   return DTSValidationStatus.VS_ISBROKEN;
  }

  if (this.Xml_NbOfRowsTag.Length == 0)
  {
   this.ComponentMetaData.FireError(0, ComponentMetaData.Name, Resource.XmlNbRowsTagNotSet, string.Empty, 0, out cancel);
   return DTSValidationStatus.VS_ISBROKEN;
  }


 }
 return DTSValidationStatus.VS_ISVALID;
}
La première étape consiste à appeler « base.Validate ». Nous implémentons nos contrôles par la suite.
En cas d'erreur nous pouvons envoyer une erreur au conteneur sur ComponentMetadata avec :
void FireError (
    int ErrorCode, /* code erreur propre  notre composant */
    string SubComponent, /* nom du composant qui lve lerreur */
    string Description, /* Une description  afficher */
    string HelpFile,
    int HelpContext,
    ref bool pbCancel /* Spcifie si ldition du composant est annule */
(je vous invite par ailleurs à sortir les messages dans une ressource pour faciliter la maintenance)
Exemple d'erreur si je ne fixe pas le filename dans le package alors qu'il est obligatoire :

 
» Démarrer une discussion
 
Discussion démarée par dystopy le 18/07/2007 à 10:52, 2 commentaire(s).