I have a variable #[User::fileExist] within my ssis package which I use to return a result if a file exists.
It is defaulted to 0 then if a file exists it will return 1. I decided to re use this variable later on in the package how do I reset this variable before using it again
Using Expression Task
SQL Server 2012 or newer
You can use an expression task to achieve this. just add an expression task to your package and use the following expression
#[User::fileExist] = 0
Read more #:
Expression Task
Use an Expression in a Data Flow Component
Using Script Task
Or you can use a script task to achieve this, just add a script task to your package, choose this variable as a ReadWrite Variable and inside the script write the following code (you have to select Microsoft Visual Basic as script Language):
Public Sub Main()
Dts.Variables.Item("fileExist").Value = 0
Dts.TaskResult = ScriptResults.Success
End Sub
You can reset the value of the variable with a Script task.
How about skipping the reset and just setting it:
Dts.Variables["fileExists"].Value = System.IO.File.Exists(filePath);
One of the standard and more transparent approaches would be creating sequence container where you want your variables to be alive. Giving them the scope of that container you will ensure that on the next iteration they are re-created.
Related
I have an Azure Logic app with an if/else conditional. In each branch I have a compose action to create some JSON. The true branch has compose and the false compose_2. After the conditional I want to send a message to a queue with the output from either branch but how do I reference the output? I have two actions("compose") and actions("compose_2"). Is there any way I can reference the output with a single variable/property name?
It is possible by using #result() which will return all the output of a scope (Condition in your case) as an array, and you can use #coalesce to find out the non-empty value between Compose and Compose_2.
However, I would use variable instead:
Declare an variable before Condition
Set the variable in each branch
Reference the variable after Condition
Problem statement: We need a way to pass a two dimensional list (or array) from one groovy script to other scripts ( to assert values from multiple DB2 tables in other scripts].
Some Background:
Step1: Based on our input xml payload we are capturing the list of nodes (and child elements) in a two dimensional list [][]. [Done]
Step2: Now we want to use the values from each of this list to assert with respect to values in DB2 tables [Also done, however keeping both step1 and step2 in same groovy script].
What we want is to to be able to pass the 2dimensional list from step1 in step2. Specially important since we have multiple tables and we dont want to either add all table steps in one big groovy script Or to duplicate step1 code in each Db2 validataion script.
We read about setting each element value from list at test case level and then reconstructing the array back but we are hesitating to use that method due to (varying &) huge size of list elements (in thousands). Question is: Are there any clean ways to achieve this?
Thanks!
As you are aware of the limitation of the earlier solution, which would only work (sharing of object between the groovy scripts) if the test case is run and does not work if individual steps are run.
Here I want to provide an approach which over comes that by using groovy's meta programming.
In script 1, have the below code:
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase
WsdlTestCase.metaClass.myList = [1,2,3,4,5]
In script 2, have the below code:
log.info "From script 2: ${context.testCase.myList}"
assert [1,2,3,4,5] == context.testCase.myList
The above even works if individual steps are run.
Hope this is helpful.
EDIT: come to understand that user required to update the list repeatedly and with metaClass user couldn't update the list. Here is the alternative:
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase
WsdlTestCase.metaClass.myObject = new Expando(myList: [1,2,3,4,5])
log.info "list initialized: ${context.testCase.myObject.myList}"
WsdlTestCase.metaClass.myObject = new Expando(myList: [1,2,3,4,5,6,7])
log.info "list updated: ${context.testCase.myObject.myList}"
You can use context
That's real working Groovy Script steps.
step1:
def array = ['Kyiv', 'Boryspil', 'Kharkiv', "L'Viv", "Odesa"]
context.setProperty('cities', array)
log.info( 'script1: '+array )
step2:
def array = context.getProperty('cities')
log.info( 'script2: '+array )
assert array.size()>0
Note:
If you run just one step, then there will be absolutely
independent context.
But if you run the whole testcase then there will be context shared
for the whole testcase.
You can use Run from here context menu in your test case window to run from exact step.
I have condition where I need to feed conditional split result based on condition (will be just one int value) to variable. Can some one help how to do this?
My actual package (Data flow):
XML Source --> Conditional split (based on condition) 2 outputs..one result based on condition (will be just one int value) need to pass it on to variable. How to achieve this?
Pure SSIS way - consume your dataflow into a Recordset Destination and then iterate through it with ForEach Loop, assigning value to the desired variable.
you have to use a script component to achieve this:
Create a script component (Choose it's type as Destination)
Double click on script component and Choose your Variable as a ReadWrite Variable. (in my example the variable is named Result
Inside the script window write the following code
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
If Not Row.inColumn_IsNull Then
Variables.Result = Row.inColumn
End If
End Sub
Side Note: Variable value does not change before dataflowtask execution is finish, to use the new value you have to continue your work in another dataflowtask
I know two ways to realize this.
First: Do it with a C# script component, this is the easiest way.
Just put a script component behind your conditional split, select your variable as "ReadWrite", then set it like that in the code:
Dts.Variables["yourvariable"].Value = Input0Buffer.Yourcolumn
I don't have access to SSIS right now, so I can't give you the exact code, but this should get you started.
Second: Write to a table and read it back with Execute SQL task. I don't really like this way ;-)
I have web request like this
Loop Controller(3)
moreSamples=true
startIndex=0
While Controller(${__javaScript(${moreSamples}==true)})
SOAP/XML-RPC Request(index=${startIndex})
Regular Expression Extractor(startIndex=newIndex,moreSamples=samples)
Now problem is I am not able to initialize moreSamples and startIndex in loop.
I tried two options:
Make moreSamples and startIndex as user defined variables. Now I am able to change their values using Regular Expression Extractor but not able to reinitialize them in outer loop using BeanShell PostProcessor like this:
vars.put("moreSamples","false")
vars.put("startIndex","0")
Make moreSamples and startIndex as User Parameters in preprocessor of of while loop but then I am not able to assign them values using Regular Expression Extractor.
Please suggest the mistakes or some new construct which can fit in.
Screenshot:
#bpsingh,
Can you do following things:
Add UserDefinedVariables on top of your Test Plan with two defined variables:
moreSamples, startIndex (like #ant suggested already)
Under the Download - PersistentSyncScope Sampler, you have two regular expression extractors in which I assume you want to extract some values and place it in these two variables from the above. Add BeanShellPostProcessor under the Download - PersistentSyncScope Sampler.
In BeanShellPostProcessor add following code:
vars.put("moreSamples","${REGEX_EXTRACT1}");
vars.put("startIndex","${REGEX_EXTRACT2}");
These two (moreSamples, startIndex) are global variables and changes on them should be visible outside of the loop.
Do you have to initialize them from the loop? How about adding those to User Defined Variables?
Or you can do it from your loop as well, the reason why it doesn't work for you is either the fact that you forgot to put the semi-colon ; after your expression(s) :
vars.put("moreSamples","false"); // ; <- was missing
vars.put("startIndex","0"); // ; <- was missing
I used BSF Sampler and it worked for me (don't forget to choose the language -> beanshell if you use this one). Here is my debug sampler (relevant part) :
START.HMS=101818
START.MS=1341821898080
START.YMD=20120709
TESTSTART.MS=1341822195274
moreSamples=false
startIndex=0
Update:
You need not to use both BSF Sampler and user defined variables. You can use either, and I see you have more user defined variables, no need for that. Have one of those at the start of your test. I'm still not clear what your problem is and what you're trying to achieve.
Actually problem here is I am using 2 loops and all answers don't take this properly into account.
Since pre/post processors are applied only to samplers not to loops there is no way to reinitialize the variables before while loop. Thus if I add initialize statements in preprocessor, loop run infinitely and if in postprocessor, it never executes. Only way to initialize is adding BSF sampler before while loop but that will spoil the reports as this sampler will also be recorded by listeners.
So only solution I found is run Download - PersistentSyncScope Sampler once and add BSF preprocessor with following scripts
vars.put("moreSamples","false");
vars.put("startIndex","0");
Now add while loop and add Download - PersistentSyncScope Sampler as its child.
That is the only solution till now. Thanks everyone to help me understand the problem.
Within a Foreach loop in SSIS is there a way that if a task fails you can break out of the loop to the next iteration?
I am looping over xml files and performing a lookup using values within this file, if the lookup doesn't return any values i'd like to report on this and then not perform any other tasks for this file. If there is no equivalent to a break statement how else can this be achieved?
You could also use a 'for' loop with a boolean condition such as looping while a variable is equal to true. Then when you want to break out of that loop, simply change the value of that variable to false and then you will break out of the loop.
Answering your question...a foreach loop, loops over a collection and other enumerable constructs so long as they exist to loop over. So you could either find a workaround, or just use a 'for' loop instead of a 'foreach' loop. That way you have more of a programming type control over the loop because you set the condition expression.
And yet another way would be to put a sequence container into your loop then put the conditional steps in the sequence container. Any decision that should 'continue' need only exit the sequence container.
Very simple to implement with all the control you could want including error trapping.
The lookup can redirect if there are no values returned, away from the successful flow.
You need the rest of your foreach loop to know there has been an error, so one way would be to set a package variable on error, just before you do the logging.
Then, in the 'success' arrow after your lookup you can change it to a conditional success, so that it only proceeds if the value of the variable is not the error value.
So I just had that problem and solved it by a) directing the failed task to a dummy task which did nothing and ended and b) setting the 'FORCEEXECUTIONRESULTS' to 'SUCCESS', which plowed through just the way I wanted it to.