3

Purpose: Fetch all the user variables that are in the SSIS package and write the variable name and their values in a SQL Server 2008 table.

What have I tried: I got a small "Script Task" working to Display the variable name and their value. The script is as follows.

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms;
namespace ST_81ec2398155247148a7dad513f3be99d.csproj
{
    [System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
    public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
    {

        #region VSTA generated code
        enum ScriptResults
        {
            Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
            Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
        };
        #endregion

    public void Main()
    {


        Microsoft.SqlServer.Dts.Runtime.Application app = new Microsoft.SqlServer.Dts.Runtime.Application();
        Package pkg = app.LoadPackage(
          @"C:\package.dtsx",
          null);
        Variables pkgVars = pkg.Variables;

        foreach (Variable pkgVar in pkgVars)
        {
            if (pkgVar.Namespace.ToString() == "User")
            {
                MessageBox.Show(pkgVar.Name);
                MessageBox.Show(pkgVar.Value.ToString());
            }
        }
        Console.Read();
    }
    }

    }

What needs to be done: I need to take this and dump the values to a database table. I am trying to work on a script component for this, but due to lack of knowledge of .net scripting, I havent gotten anywhere close to the finish line. This is what I have done on the component side.

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Microsoft.SqlServer.Dts;
using System.Windows.Forms;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{

   public override void CreateNewOutputRows()
    {

        #region Class Variables
        IDTSVariables100 variables;
        #endregion

        variables = null;

        this.VariableDispenser.GetVariables(out variables);
        foreach(Variable myVar in variables)
        {
            MessageBox.Show(myVar.Value.ToString());
            if (myVar.Namespace == "User")
            {
                Output0Buffer.ColumnName = myVar.Value.ToString();
            }
        }
    }

}
rvphx
  • 2,324
  • 6
  • 40
  • 69

1 Answers1

3

I can think of 2 ways of solving this issue right now .

  1. Use the same script task to insert the values into the Database
  2. using Foreach loop to enumerate the ssis package variables ( as you have asked )

Table Script for inserting the variable name and value is

CREATE TABLE [dbo].[SSISVariables]
(
[Name] [varchar](50) NULL,
[Value] [varchar](50) NULL
)

1.Use Script task and write the below code

[System.AddIn.AddIn("ScriptMain", Version = "1.0", Publisher = "", Description = "")]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
    private static string m_connectionString = @"Data Source=Server Name;
    Initial Catalog=Practice;Integrated Security=True";
   public void Main()
    {
       List<SSISVariable> _coll = new List<SSISVariable>();
        Microsoft.SqlServer.Dts.Runtime.Application app = new Microsoft.SqlServer.Dts.Runtime.Application();
        Package pkg = app.LoadPackage(PackageLocation,Null);
                   Variables pkgVars = pkg.Variables;

        foreach (Variable pkgVar in pkgVars)
        {
            if (pkgVar.Namespace.ToString() == "User")
            {
                _coll.Add(new SSISVariable ()
                {
                 Name =pkgVar.Name.ToString(),
                 Val =pkgVar .Value.ToString () 
                });
           }
        }
        InsertIntoTable(_coll);
        Dts.TaskResult = (int)ScriptResults.Success;
    }

    public void InsertIntoTable(List<SSISVariable> _collDetails)
    {  
       using (SqlConnection conn = new SqlConnection(m_connectionString))
        {
            conn.Open();
            foreach (var item in _collDetails )
            {
             SqlCommand command = new SqlCommand("Insert into SSISVariables values (@name,@value)", conn);
             command.Parameters.Add("@name", SqlDbType.VarChar).Value = item.Name ;

             command.Parameters.Add("@value", SqlDbType.VarChar).Value = item.Val ;
             command.ExecuteNonQuery();    
            }
        }
     }
  }

   public class SSISVariable
   {
    public string Name { get; set; }
    public string Val { get; set; }
   }

Explanation:In this ,i'm creating a class which has properties Name and Val . Retrieve the package variables and their value using your code and store them in a collection List<SSISVariable> .Then pass this collection to a method (InsertIntoTable) which simply inserts the value into the database by enumerating through the collection .

Note :

There is a performance issue with the above code ,as for every variable 
im hitting the database and inserting the value.You can use
[TVP][1]( SQL Server 2008)   or stored procedure which takes
 xml( sql server 2005) as input. 

2.Using ForEach Loop

Design

enter image description here

Step 1: create a Variable VariableCollection which is of type System.Object and another variable Item which is of type String to store the result from Foreach loop

Step 2: For the 1st script task .

VariableCollection is used to store the Variable name and its value enter image description here

Step 3: Inside the script task Main Method write the following code

  public void Main()
   {
     ArrayList _coll = new ArrayList(); 

        Microsoft.SqlServer.Dts.Runtime.Application app = new Microsoft.SqlServer.Dts.Runtime.Application();
        Package pkg = app.LoadPackage(Your Package Location,null);

        Variables pkgVars = pkg.Variables;
        foreach (Variable pkgVar in pkgVars)
        {
            if (pkgVar.Namespace.ToString() == "User")
            {
                _coll.Add(string.Concat ( pkgVar.Name,',',pkgVar.Value ));
            }
        }
        Dts.Variables["User::VariableCollection"].Value = _coll;
        // TODO: Add your code here
        Dts.TaskResult = (int)ScriptResults.Success;
    }

Step 4: Drag a Foreach loop and in the expression use Foreach from Variable Enumerator

enter image description here

Step 5:Foreach loop enumerates the value and stores it in a variable User::Item

enter image description here

Step 6:Inside the foreach loop drag a script task and select the variable

readonly variables   User::Item 

step 7: Write the below code in the main method

   public void Main()
    {
      string name = string.Empty;
      string[] variableCollection;
      variableCollection = Dts.Variables["User::Item"].Value.ToString().Split(',');
      using (SqlConnection conn = new SqlConnection(m_connectionString))
        {
            conn.Open();
            SqlCommand command = new SqlCommand("Insert into SSISVariables values (@name,@value)", conn);
            command.Parameters.Add("@name", SqlDbType.VarChar).Value = variableCollection[0];

            command.Parameters.Add("@value", SqlDbType.VarChar).Value = variableCollection[1];

            command.ExecuteNonQuery();
        }
        // TODO: Add your code here
        Dts.TaskResult = (int)ScriptResults.Success;
    }

Explanation : In the Foreach loop ,i can only enumerate one variable .So the logic is, i need to somehow pass the variable name and its value into one variable .And for this ,i have concatenated name and value

 string.Concat ( pkgVar.Name,',',pkgVar.Value )

Script task in the foreach loop simply splits the variable and stores it into a array of string and then u can access the name and value using array index and store it in the database

praveen
  • 12,083
  • 1
  • 41
  • 49
  • Thank you Praveen for responding. It makes complete sense what you are doing. After I put the question here, I was wondering if this approach would log the run time variable values? Without testing your code, will it be able to handle the run time values? – rvphx Aug 06 '12 at 15:04
  • @RajivVarma : The result is stored as object data type .So no matter what ever be the variable value the above code should work .I have tested with string and int variables and they worked perfectly fine – praveen Aug 06 '12 at 15:54
  • I was hoping that this would have worked as I had expected to, but doesnt look like it does. I have an Execute SQL Task which returns the count from a table and stores that count value on the variable. I traced the variable and looks like the 1st method only stores the static value of the variable as opposed to the run time. – rvphx Aug 06 '12 at 20:18
  • @RajivVarma : Your actually having 2 instances of the same ssis package .One which your are running from BIDS environment and the other one in same enironment using script task .In script task you are actually loading a packaging which just reads the metadata (nothing to do with runtime) .So its showing static values . – praveen Aug 07 '12 at 01:11
  • Just to prove that im not bluffing ,in your script task add the variable (In readonly valriable) which your changing it using execute sql task (to find the count).Now write the following code MessageBox.Show(Dts.Variables[User::YourCountVariable].Value.toString()) .This will actually print the count not the static value – praveen Aug 07 '12 at 01:13
  • There is one more way of solving this issue using onVariablechanged Event .The Logic is whenever a variable value changes this event will be fired and i ll be inserting this data(Name and value) into DB .Then again at the end of control flow i ll call the above script task which will execute a SP which inserts those variable which are static(whose value hasn't changed at run time).This static check will be performed in the SP .Let me know if ur still struggling to find the sol – praveen Aug 07 '12 at 13:12
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/15011/discussion-between-rajiv-varma-and-praveen) – rvphx Aug 07 '12 at 15:35