How to make a Script Component Failure in Data Flow Task? - ssis

I have a requirement that is columns validation in the Script component. If the column value found null it should be stopped task with red cross mark and then the task should be the exit.
I have used below code to fail the script component task. But it's not stopping the task, it passing the next code line.
DTSExecResult result;
result = DTSExecResult.DTSER_FAILURE;

If you just force an error and prevent further execution from the Script Component you can throw an error as done below. However you'll want to make sure this is defined well enough to distinguish it from any other errors that may occur.
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
if (Row.Column1_IsNull)
{
throw new Exception("Error Message");
}
}

Dts.TaskResult = (int)ScriptResults.Failure;
return this from the script task

Related

SSIS ScriptTask OnTaskFailed event handler not capturing the ScriptResults.Failure result

This is something that is really down to fairly advance knowledge of the .NET framework but I haven't been able to find the information I needed.
I have an SSIS package that executes a ScriptTask. Within that ScriptTask the below simple code:
public void Main()
{
// TODO: Add your code here
var fileName = (string)Dts.Variables["User::FileName"].Value;
DialogResult result = MessageBox.Show($"Do you want to fail the task", "Select what to do" , MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
Dts.TaskResult = (int)ScriptResults.Failure;
} else
{
Dts.TaskResult = (int)ScriptResults.Success;
}
}
As you can see, it quite difficult to write any simpler code. My question is around the event handler for this script task.
I have tried the following:
Adding an OnTaskFailed event handler to the Script task
Adding an OnError event handler to the script task
Outcome has been as follows:
Event handler does not trigger, meaning that the task result returned by Dts.TaskResult = (int)ScriptResults.Failure; does not have an impact to the package.
Event handler does trigger, meaning that the task result returned by Dts.TaskResult = (int)ScriptResults.Failure; is captured by the event handler.
I would have expected to be the other way around. Can anyone explain why this is the case? To me OnError is a more generic outcome and I wouldn't like my event handler to trigger on every single error (e.g. unhandled exceptions).
Hope this makes sense

Error #1023: Stack overflow occurred

I've read a lot of posts about this error. Yet it does not solve my problem. In my case, there are loop working through two funcions like this:
function getData() {
//doing some stuff here
call_socket("data", callback); //When response from socked server has been received, call callback function
}
function callback(data:Object) {
if(!data) { getData(); } //if data is null, continue loop
else { //stop the loop }
}
I got an error on both of these functions:
Error #1023: Stack overflow occurred.
I understand that this error tells me that I'm calling the functions repeatedly, but in my case, that is what I got to do there.
Is there any way to solve this?
The problem is in the logic of your code. Just think about situation when your call_socket does not return data for some time. This will result in numerous circles of callback and getData. Depending on your app you can achieve desired result in 2 ways:
You should use some Event to notify other parts of your app that the data has arrived (instead of callback)
You can poll the server at defined time spans. You may use Timer for this.

Deferring PropertyChanged events until view bindings setup complete

A number of our MVVMcross views depend remote services to fully display themselves. We typically kick this off a Task in ViewModel's Init() using to get it async. ViewModel properties are set in the Task upon completion, UI updated via PropertyChanged notifications.
Sometimes the remote data (and task) completes before the View has bound it's listeners and thus no property changed event is received.
This issue is touched on at async Init and Property Changed in MvvmCross but the solution feels like duplication of presentation logic.
We've had success buffering PropertyChanged notifications until the end of ViewDidLoad, but we'd like to turn below into a more generic solution by hooking into the MVX framework.
Is there a way to hook mvvmcross's view creation to fire our code off after viewDidLoad completes?
Base View Model
public abstract class BaseViewModel : MvxViewModel{
protected bool _deferPropertyChangedEvents = true;
private readonly List<PropertyChangedEventArgs> _deferedPropertyChangedEvents = new List<PropertyChangedEventArgs>();
public override void RaisePropertyChanged(PropertyChangedEventArgs changedArgs)
{
lock(_deferedPropertyChangedEvents){
if (!_deferPropertyChangedEvents)
{
base.RaisePropertyChanged(changedArgs);
}
else
{
// buffer it up
_deferedPropertyChangedEvents.Add(changedArgs);
}
}
}
public void EndDeferringPropertyChangedEvents()
{
lock(_deferedPropertyChangedEvents){
_deferPropertyChangedEvents = false;
// playback all buffered notifications
foreach (var e in _deferedPropertyChangedEvents)
{
RaisePropertyChanged(e);
}
_deferedPropertyChangedEvents.Clear();
}
}
}
Sample view
public class SomeView : MvxViewController
{
public override void ViewDidLoad()
{
base.ViewDidLoad();
var bindings = this.CreateBindingSet<StopView, SomeViewModel>();
.....
bindings.Apply();
// plays back any PropertyChanged() notifications that were buffered
// up while the view was initializing
// ---> want to find a way to have MVX call this
ViewModel.EndDeferringPropertyChangedEvents();
}
}
As a simple answer, I believe your own line can easily be called using a BaseViewModel cast:
// ---> want to find a way to have MVX call this
((BaseViewModel)ViewModel).EndDeferringPropertyChangedEvents();
However, on a more technical note, I think it might be useful to further examine and understand why this Deferring code is necessary - to further take a look at what the underlying threading problems are.
There are a number of factors that are puzzling me at present::
During the line bindings.Apply(); all current bound property values should be transferred from the ViewModel to the View - so calling EndDeferringPropertyChangedEvents(); in the next line should (in theory) only rarely get different values.
Further, the default MvvmCross RaisePropertyChanged method changed notifications across to the UI thread. Because ViewDidLoad is also invoked on the UI thread, this means that any RaisePropertyChanged calls made on background threads during ViewDidLoad should all be automatically deferred until after ViewDidLoad has finished and the UI thread becomes available.
Looking at the MvxNotifyPropertyChanged code, the only potential gap I can see where mutli-threading might find a way through this automatic RaisePropertyChanged deferral is in this optimisation check:
// check for subscription before potentially causing a cross-threaded call
if (PropertyChanged == null)
return;
(from https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNotifyPropertyChanged.cs#L76)
If your ViewModel Init method is also using async for it's Task management, then this async code should also be using the UI thread - so the "callback" of this async operation should also be marshalled back to the UI thread (and so shouldn't be executed during ViewDidLoad itself).
As I said, these factors are puzzling me - I don't have a definitive answer/explanation - sorry! But I'd love to see an example problem and to try to help solve it at a generic level.

Try/catch, don't know how to loop this

Here is my main method
public static void main (String[] args) {
Scanner console = new Scanner(System.in);
Intro();
try {
userInput(console);
} catch (InputMismatchException e) {
System.out.println("Not a number; try again.");
}
}
I would like the userInput(console); to run again even if the Exception was found. The method userInput(console); runs a program that asks for the radius of a circle and calculates its diameter, circumference, and area. I tried using a while loop outside of the try/catch statement but I don't know what I should use as conditions. Comment if you would like to see the userInput(console) method and I will post that as well.
Using a while loop with a condition is ok. Just remember that the condition serves as a flag to define if the iteration should carry on or stop, in particular because a certain condition was met. In this case, your condition is defined by the user's input validation result. Assuming you used a while like this:
while(someCondition) {
try {
userInput(console);
} catch (InputMismatchException e) {
System.out.println("Not a number; try again.");
}
}
Your someCondition variable should be a boolean initialized in true that is set to false when the input is valid or, in your case, when no exception is thrown. You can also set it to false after a certain amount if iterations. If you set someCondition to false, the next time the while evaluates someCondition it is false, and the iteration ends.
Another approach is to use a while(true) loop and end the iteration by using a break statement. It achieves the same in this case, but they're essentially different:
The someCondition approach doesn't cut the current iteration, it lets it finish the processing (considering you have something in the loop that must be done with the valid input, for example).
By using a break statement, that iteration is interrupted and the while loop ends without executing the rest of the code encased inside of it.

Adobe Air, packaged install fails with my trace routine... how come?

I cobbled together some code from here and there for a trace I like... it generates an error to get a stack trace and picks out the traced routine name, I like that detail in the trace log.
Problem: it fails in an installed AIR file. I wonder why? I don't expect it to do anything as is... just, I'd prefer it not cause the program to fail!
tx
artie
enter code here
static public function XTRACE( ... traceArgs ):void {
try {
throw new Error(); // make a stack
} catch (e:Error) {
var stack:String = e.getStackTrace();
var frames:Array = stack.split("\n");
var myFrame:String = String(frames[2]);
myFrame = myFrame.replace("\t", "");
// "at " can be followed by some part of the package
// you don't want to see. E.g., if your code is all in
// com.foo.bar, you can put "at com.foo.bar." so as not
// to crowd the display
myFrame = myFrame.substr("at ".length);
myFrame = myFrame.substring(0, myFrame.indexOf("["));
var now:Date = new Date();
trace(new Date().toLocaleTimeString() + ":" + myFrame + ": " + traceArgs.join(" "));
}
}
In what way is your app failing?
1) Trace routines are for debugging, so your trace won't do anything in an installed app.
2) I'm not sure when you call this routine, but it seems weird that you have a routine that only throws an error. I think in this code the 'catch' is only going to get entered if there's an error throwing the error. Normally you would try to perform some useful action, and catch errors when something goes wrong.
Within the trace function your attempting to invoke the Date().toLocaleTimeString() statically before it becomes instantiated by the new keyword. Try the following instead:
trace((new Date()).toLocaleTimeString() + ":" + myFrame + ": " + traceArgs.join(" "));
thanks for your input Fergal. The XTRACE function works fine running with the debug player, and fails only when running with the release player. So I assume the code line I use must associate values in the right order... I settled on using a function I didn't know about before:
enter code here
static public function XTRACE( ... traceArgs ):void {
if ( Capabilities.isDebugger ) {
With that, XTRACE does nothing unless it is executing in a debug environment. So it works around the issue. I'll still use your brackets though, I like to make order of association obvious too ;-)
I realize you've probably grown old and forgot what flash is since you asked this question. But, you're getting an NPE because e.getStackTrace() returns null in the release player.
A couple other things:
You don't need to throw the error to get a stack trace; new Error().getStackTrace() works fine.
Since this is debug code, and the calling code probably isn't expecting errors, you should wrap the whole thing in a try catch.
The compiler won't resolve 'at '.length, so it will be called every time at runtime. Unless you're really paranoid, you can just hard code it to 3.
Both the substrs can be combined into 1
The now variable isn't used.