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

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

Related

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

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

Init SqlDependency and notify changes

I need something telling to my app when someone has updated data in the database. If I don't have misunderstood, SqlDependancy is what I need. I have followed this tutorial and write this code:
class dbListener
{
public dbListener()
{
Debug.WriteLine(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=12345;");
SqlDependency.Start(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=12345;");
connection = new SqlConnection(MainWindow.dbContext.Database.Connection.ConnectionString + "Password=12345;");
connection.Open();
SomeMethod();
}
SqlConnection connection;
void SomeMethod()
{
// Assume connection is an open SqlConnection.
// Create a new SqlCommand object.
//{
using (SqlCommand command = new SqlCommand("SELECT * FROM dbo.ArchivioErogazioni", connection))
{
// Create a dependency and associate it with the SqlCommand.
SqlDependency dependency = new SqlDependency(command);
// Maintain the refence in a class member.
// Subscribe to the SqlDependency event.
dependency.OnChange += new OnChangeEventHandler(OnDependencyChange);
// Execute the command.
command.ExecuteReader();
// }
}
}
// Handler method
void OnDependencyChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
// Handle the event (for example, invalidate this cache entry).
MessageBox.Show("ikjkjkj");
Debug.WriteLine("fkldjkfjklgjf");
SqlDependency dependency = (SqlDependency)sender;
dependency.OnChange -= OnDependencyChange;
SomeMethod();
}
}
void Termination()
{
// Release the dependency.
SqlDependency.Stop(MainWindow.GetConnectionString("Model"));
}
}
but it doesn't work. I mean, it runs without errors, but when I try to test it, updating some values from the SQL Server 2008 Management Studio, nothing happens. I have put a breakpoint in the function that would manage the event, but it is fired only in the init phase.
Have I done mistakes? How can I reach my goal?
but it is fired only in the init phase
It fires because your query notification subscription is invalid. You must inspect the SqlNotificationEventArgs members. Only the Change type is a notification for change, you are probably getting a Subscribe type with Statement source. Your query does not meet the criteria described in Creating a Query for Notification:
The statement may not use the asterisk (*) or table_name.* syntax to specify columns.

AS3: Returning value from another function after event happened

Basically I want to check if a user exists in a database using AMF (and that works great!). But then I want to return the boolean value to another function (in another class) that originally called the "checkUserExistance" function. But, since the database connection isn't immidiate, this function will always return a false value (even if "result" is true). So I would like to have the return-line inside the "onUserChecked"-function but that of course gives me an error. I thought I could create an eventListener, but then, the "return userExists"-line would also have to be inside another function, which doesnät work(?)... What can I do?
public function checkUserExistance(username:String) {
var responderBOOLEAN:Responder = new Responder(onUserChecked, onFault)
var userExists:Boolean = false;
connection.connect(gateway);
connection.call("User.checkUser", responderBOOLEAN, username);
connection.close();
function onUserChecked(result:Boolean):void {
userExists = result;
}
return userExists;
}
I'm sorry but you are trying to force an Asynchronous call to a Synchronous one and this is WRONG.
See here
You should learn how to handle events in the correct way.
What can i suggest you that helped me a lot is this
The only true answer here is to save userExists as a member variable, and dispatch event when the server returns you a response. The client side of the things should be similar to:
// add listener, ServerEvent is a custom event (see below)
server.addEventListener(ServerEvent.CHECK_RESPONSE, onCheckResponse);
server.checkUserExistance('username'); // start the query
function onCheckResponse(e:ServerEvent):void {
if (e.userExists) {
}
}
// inside server class
function onUserChecked(result:Boolean):void {
userExists = true;
dispatchEvent(new ServerEvent(ServerEvent.CHECK_RESPONSE, userExists));
}
/* ServerEvent is a custom class that extens Event
Such classes are used so you can pass special properties in them
via constructor (pass data, store it into member variable)
and through getter for that variable.
If you don't like it, simply add/dispatch Event.COMPLETE
and use public property to get userExists from server
*/

AS3 Asynchronism problems

I had a strange bug in my program which I fortunately found quite quickly but am still puzzled why it was happening. Essentially it was to do with the order of commands in the source code and event listeners, here is the example:
function detectFaces(loader:ImageLoader)
{
var detector:FaceDetector=new FaceDetector();
detector.addEventListener(FaceDetectorEvent.FACE_CROPPED,facesDetected);
detector.loadFaceImageFromBitmap(loader.bitmap);
var something:Number = stage.width;
function facesDetected(e:FaceDetectorEvent):void{
trace(something);
}
}
Operation that raise the event here is not important, only thing to note about it would be it takes around 100ms. What I get as trace output is NaN and I don't know why that is since line declaring the variable something will definitely be called before callback of facesDetected and it is in scope of the handler function declared under it. This problem was easy to solve by just moving var something:Number = stage.width; before loadFaceImageFromBitmap(..) method, but I would really like to know why this is happening?
I am suspecting this is not due to order of execution but has something to do with passingByValue and passingByRefrence deferences but don't know how would these cause an error like this.
EDIT: Now I am even more puzzled... This code works in any order of declaration:
timers();
function timers()
{
var timerTest:Timer = new Timer(100,1);
timerTest.addEventListener(TimerEvent.TIMER,onTime);
//BEFORE DECLARATION
timerTest.start();
var something:Number = stage.width;
function onTime(e:Event)
{
trace("SOMETHING :"+something);
}
}
timers();
function timers()
{
var timerTest:Timer = new Timer(100,1);
timerTest.addEventListener(TimerEvent.TIMER,onTime);
var something:Number = stage.width;
//AFTER DECLARATION
timerTest.start();
function onTime(e:Event)
{
trace("SOMETHING :"+something);
}
}
With regard to your initial question, actionscript will complete the execution of a block of code before it continues to execute subsequent lines. If there was nothing asynchronous happening in your loadFaceImageFromBitmap method (ie, if your weren't using a Loader or some other object that had to wait for an event to fire) then, however long the code takes to execute, the FACE_CROPPED event will still fire before 'something' is set to a value.
As for the other problem, it looks to me like the answer is simply that you're using a TimerEvent - Actionscript will acknowledge that it shouldn't wait for the event to fire before continuing to execute code; It will, therefore, declare 'something' before the 100 miliseconds passes. So, in this case, because you're using an event, the code WILL continue 'reading' and executing the lines following the event listener.
The code of the function loadFaceImageFromBitmap run on a sync way. The FaceDetectorEvent.FACE_CROPPED event listener is invoked inside of that function, it is not a callback declared to run after some response is returned for ie(http request).
In the case of the Timer it works as expected, because event listener is not invoked right at the start moment, it waits for X time.

Flex: NetStatusEvent not fired by Local Shared Object. Why?

This is what I do: In the 'Local Storage' dialog I set the pointer to 'None' to allow 0 kB. Then I run my code. I get the 'Local Storage' dialog with an [Allow] and [Deny] button. I click [Deny]
The output I get is
2. we are here now
3. adding a handler to the SharedObject
NOTE: The onFlushStatus event handler is NOT called.
I repeat the above stuff, but now click [Allow].
The output I get is the same:
2. we are here now
3. adding a handler to the SharedObject
NOTE: The onFlushStatus event handler is NOT called.
I was using the code from here
Flex: How to detect if user has blocked shared object from writing
Whatever I try (and I tried much), the event handler gets never called on a [Allow] or [Deny] button click. But I want to know which button the user clicked.
var so: SharedObject = null;
var flushStatus: String = null;
so = SharedObject.getLocal('mySpace');
try {
flushStatus = so.flush();
} catch (error: Error) {
trace('1. could not write SharedObject to disk');
}
trace('2. we are here now');
if (flushStatus == flash.net.SharedObjectFlushStatus.PENDING) {
trace('3. adding a handler to the SharedObject');
so.addEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
}
public function onFlushStatus(event: NetStatusEvent): void
{
trace('4. in event handler');
}
As suggested I changed my code and added the event listener before calling flush(). Then I run my tests again. Unfortunately my onFlushStatus() is not called.
var so: SharedObject = null;
var flushStatus: String = null;
so = SharedObject.getLocal('mySpace');
trace('0. adding a handler to the SharedObject');
so.addEventListener(NetStatusEvent.NET_STATUS, onFlushStatus);
flushStatus = so.flush();
trace('2. we are here now');
public function onFlushStatus(event: NetStatusEvent): void
{
trace('4. in event handler');
}
The output I get for [Deny]
0. adding a handler to the SharedObject
2. we are here now
The output I get for [Allow]
0. adding a handler to the SharedObject
2. we are here now
The onFlushStatus() is not called.
From this link it appears that so.flush is returning a String with the result of the flush() command. Rather than looking for an event to be fired you should look at the value of the return. If it's a pending then add your event listener and check success/fail.
A good example: here