{heroes}... i wish, i was

May 2009 - Posts

  • Custom SSIS Component: The Engine

    download sample code

    SSIS Component yang akan saya buat merupakan hasil rewrite dari Script Component yang saya tulis disini. Component ini berfungsi untuk melakukan transformasi memgambil data tertinggi dan membuang sisanya.

    Jadi, kalau diperhatikan dengan seksama component-nya harus memiliki requirement (duh requirement, kayak bikin project) sebagai berikut:

    • Merupakan Data Flow Component untuk Transformasi
    • Mengambil data tertinggi dari data-data yang masuk ke dalam component-nya
    • Kalau bisa sih, data-data yang diluar data tertinggi bisa diarahkan apabila kita ingin men-transformasi sisa data tersebut
    • Supaya mudah, Custom Component-nya dikasih nama Top Data

    Membuat component ini sangat mudah, sama seperti kita membuat sebuah library lain dengan menggunakan .NET. Yang menjadi pre-requisite adalah Microsoft SQL Server SDK yang harus sudah terinstal.

    Pertama kita buat sebuah Class Library dengan nama TopData

    Kemudian tambahkan reference Microsoft.SqlServer.DTSPipelineWrap, Microsoft.SQLServer.DTSRuntimeWrap, Microsoft.SQLServer.ManagedDTS, Microsoft.SqlServer.PipelineHost ke dalam project.

    Setelah itu ubah nama file Class1.cs dengan TopData.cs

    Tambahkan Using directive berikut di TopData.cs

       1:  using Microsoft.SqlServer.Dts.Pipeline;
       2:  using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
       3:  using Microsoft.SqlServer.Dts.Runtime;
       4:  using Microsoft.SqlServer.Dts.Runtime.Wrapper;

    Karena kita akan membuat pipeline component, maka TopData harus di-inherit dari class PipelineComponent, lalu tambahkan attribute untuk TopData

       1:      [DtsPipelineComponent(DisplayName="Top Data",ComponentType=ComponentType.Transform)]
       2:      public class TopData : PipelineComponent 

    Setelah selesai, langkah berikutnya adalah melakukan inisialisasi TopData. Proses inisialisasi terjadi pada method ProvideComponentProperties. Yang harus diinisialisasi adalah property, input dan output dari TopData. Berdasarkan requirement diatas berarti kita harus menambahkan property untuk menyimpan jumlah top row, property untuk mengatur sisa data yang berada di luar top, satu input, satu output untuk top row, satu output untuk sisa row

       1:          public override void ProvideComponentProperties()
       2:          {
       3:              IDTSCustomProperty100 nTopProperty = ComponentMetaData.CustomPropertyCollection.New();
       4:              nTopProperty.Name = "Top";
       5:              nTopProperty.Description = "Number of top rows";
       6:              nTopProperty.Value = 10;
       7:   
       8:              IDTSCustomProperty100 nRestBehaviorProperty = ComponentMetaData.CustomPropertyCollection.New();
       9:              nRestBehaviorProperty.Name = "RestBehavior";
      10:              nRestBehaviorProperty.Description = "Threat rows outside top";
      11:              nRestBehaviorProperty.Value = RestBehavior.Remove;
      12:   
      13:              IDTSInput100 input = ComponentMetaData.InputCollection.New();
      14:              input.Name = "Input";
      15:   
      16:              IDTSOutput100 outputTop = ComponentMetaData.OutputCollection.New();
      17:              outputTop.Name = "Top Output";
      18:              outputTop.ExclusionGroup = 1;
      19:              outputTop.SynchronousInputID = input.ID;
      20:   
      21:              IDTSOutput100 outputRest = ComponentMetaData.OutputCollection.New();
      22:              outputRest.Name = "Rest Output";
      23:              outputRest.ExclusionGroup = 1;
      24:              outputRest.SynchronousInputID = input.ID;
      25:          }

    Selanjutnya adalah melakukan validasi component. Proses validasi ini untuk memastikan agar pada saat package dieksekusi tidak terjadi error yang disebabkan error dari TopData, ataupun constraint untuk Top Data. Untuk TopData, yang akan divalidasi adalah nilai Top yang dimasukkan harus lebih besar dari 0.

     

       1:          public override DTSValidationStatus Validate()
       2:          {
       3:              try
       4:              {
       5:                  _topRow = (int)ComponentMetaData.CustomPropertyCollection["Top"].Value;
       6:                  if (_topRow <= 0)
       7:                  {
       8:                      ComponentMetaData.FireError(0, ComponentMetaData.InputCollection[0].Name, "Top value should be greater than 0", string.Empty, 0, out  _cancel);
       9:                      return DTSValidationStatus.VS_ISBROKEN;
      10:                  }
      11:              }
      12:              catch (Exception ex)
      13:              {
      14:                  ComponentMetaData.FireError(0, ComponentMetaData.InputCollection[0].Name, ex.Message, string.Empty, 0, out  _cancel);
      15:                  return DTSValidationStatus.VS_ISBROKEN;
      16:              }
      17:   
      18:              _restBehavior = (RestBehavior)ComponentMetaData.CustomPropertyCollection["RestBehavior"].Value;
      19:              if (_restBehavior == RestBehavior.SendToRestOutput && !ComponentMetaData.OutputCollection[1].IsAttached)
      20:              {
      21:                  ComponentMetaData.FireWarning(0, ComponentMetaData.OutputCollection[1].Name, this.ComponentMetaData.Name + " is configure to send rest output, but no output is attached", string.Empty, 0);
      22:              }
      23:   
      24:              return DTSValidationStatus.VS_ISVALID;
      25:          }

     

    Pada saat package akan dieksekusi, kita dapat mempersiapkan settingan terakhir agar component berjalan dengan baik dengan menggunakan method PreExecute

       1:          public override void PreExecute()
       2:          {
       3:              _topRow = (int) ComponentMetaData.CustomPropertyCollection["Top"].Value;
       4:              _restBehavior = (RestBehavior)ComponentMetaData.CustomPropertyCollection["RestBehavior"].Value;
       5:              _counter = 0;
       6:              _isTop = true;
       7:   
       8:              _topOutputID = ComponentMetaData.OutputCollection[0].ID;
       9:   
      10:              if (_restBehavior == RestBehavior.SendToRestOutput)
      11:              {
      12:                  _restOutputID = ComponentMetaData.OutputCollection[1].ID;
      13:              }
      14:          }

     

    Yang terakhir dan merupakan hasil dari apa yang telah kita kerjakan dari atas tadi adalah proses eksekusi package. Code dibawah ini akan mengirim top row ke Top output, dan mengirim sisanya ke Rest Output.

       1:          public override void ProcessInput(int inputID, PipelineBuffer buffer)
       2:          {
       3:              if (_restBehavior == RestBehavior.Remove)
       4:              {
       5:                  ProcessBufferWithRemove(buffer);
       6:              }
       7:              else
       8:              {
       9:                  ProcessBufferWithSendOutput(buffer);
      10:              }
      11:          }
      12:   
      13:          private void ProcessBufferWithRemove(PipelineBuffer buffer)
      14:          {
      15:              while (_isTop && buffer.NextRow())
      16:              {
      17:                  if (_counter < _topRow)
      18:                  {
      19:                      _counter++;
      20:                      buffer.DirectRow(_topOutputID);
      21:                  }
      22:                  else
      23:                  {
      24:                      _isTop = false;
      25:                  }
      26:              }
      27:          }
      28:   
      29:          private void ProcessBufferWithSendOutput(PipelineBuffer buffer)
      30:          {
      31:              while (buffer.NextRow())
      32:              {
      33:                  if (_counter < _topRow)
      34:                  {
      35:                      _counter++;
      36:                      buffer.DirectRow(_topOutputID);
      37:                  }
      38:                  else
      39:                  {
      40:                      buffer.DirectRow(_restOutputID);
      41:                  }
      42:              }
      43:          }

     

    Baca juga:

    Creating Custom SSIS Component

    Custom SSIS Component: The UI

    Custom SSIS Component: The Icon

    Custom SSIS Component: The Installer

    Share this post: | | | |
  • Creating Custom SSIS Component

    Hal yang saya suka dari SSIS adalah object model yang mengijinkan saya membuat custom component, baik component di Control Flow yang disebut Custom Task ataupun component di Data Flow yang disebut Custom Data Flow Component.

    Di control flow kita mengenal sebuah task bernama Script Task untuk membuat code dengan menggunakan VB .net atau C# sebagai language-nya apabila built-in task yang disediakan tidak dapat mengakomodir kebutuhan proses. Sedangkan di data flow terdapat Script Component.

    Apabila Anda sering menulis Script Task atau Script Component yang isi script-nya relatif sama, maka itu tandanya Anda harus melakukan refactoring dengan mengubah Script Task/Script Component tadi menjadi sebuah Custom Component. Kenapa? karena hal ini akan menjadikan proses development menjadi lebih cepat sebab kita tidak harus bersusah-susah membuka script editor untuk menulis code-nya. Selain itu, apabila script-script tadi harus diubah, atau butuh diperbaiki kita hanya tinggal memperbaiki/menambahkan code pada custom component dan bukan memperbaiki semua script yang terdapat pada Script Task/Script Component. Selain itu, apabila kita melihat ukuran file .dtsx-nya kita akan mendapati selisih ukuran yang signifikan jika membandingkan keduanya.

    Beberapa waktu lalu, pada saat mengerjakan sebuah project, saya mendapati beberapa script component yang memiliki fungsi hampir sama. Script Component itu melakukan transformasi untuk mengambil data tertinggi dan membuang sisanya. Sebuah script yang fungsinya hampir sama dengan Top Clause yang terdapat di T-SQL.

    Pada beberapa tulisan berikutnya, saya akan menunjukkan bagaimana menulis ulang script component tadi menjadi sebuah Custom Component.

     

    Baca juga:

    Custom SSIS Component: The Engine

    Custom SSIS Component: The UI

    Custom SSIS Component: The Icon

    Custom SSIS Component: The Installer

    Share this post: | | | |