Showing posts with label calls. Show all posts
Showing posts with label calls. Show all posts

Wednesday, February 15, 2012

Error Handling with Execute Package Task

I have a main package that calls several other packages using Execute Package Tasks. I also have OnPreExecute, OnPostExecute, and OnError event handlers at the package level to audit the beginning and completion of each package. I want to prevent each task from bubbling up to the package event handlers as well as prevent each task from bubbling up to the main package event handlers. I've tried setting the Propagate variable for each of the event handlers to False and setting the DisableEventHandlers property of each task to True but neither solution seems to work. Is there a way to do this that I'm missing?

You have to set [System::Propogate]=false in the eenthandler of the task for which you don't want events to propogate.

Your post doesn't specify on which eventhandlers you are setting this.

-Jamie

|||

I found another thread that describes the problem I'm seeing. Here is the previous thread and, in following the thread, I'm not sure if the conclusion was that this behavior was as designed or that this is really a bug. Here is a link to the previous discussion:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=57523&SiteID=1

The problem in a nutshell is the following: There are two packages, a parent package which calls a child package using the Execute Package Task. Both packages have OnPostExecute event handlers defined at the package level to log progress with different ExecutionInstanceGUID. Even when the System::Propagate property is set to False for the child package OnPropagate event handler, the parent OnPostExecute event handler is still raised.

I guess the work around is to create an empty event handler for the Execute Package Task in the parent package and set the System::Propagate property for that empty event handler to False to prevent the main package OnPostExecute event from being raised. Since I have several Execute Package Tasks in the real solution, a better approach would be to wrap all the Execute Package Tasks in a Sequence container and create the do nothing event handler with the Propagate property set to false at the Sequence container rather than at each of the Execute Package tasks event handlers.

Does this make sense? Or is there possibly a better solution that I'm missing? Have to confess, I'm getting a bit overwhelmed by the number of possible appoaches one can use to log and audit package execution.

|||

Martin,

I cannot replicate your problem. If I set System::Propogate=FALSE on an eventhandler scoped to the child package then any events raised by the package container of the child package do not propogate to the parent package.

Note that this does NOT stop events raised by containers in the child package from propogating to the parent package. If you want to stop this from happening then set System::Propogate=FALSE on all of those containers as well.

I've also re-read your first post where you say "I want to prevent each task from bubbling up to the package event handlers ". If you only want to capture events fired by the package then you can compare System::PackageID to System::SourceID. If they are different then the event has not been raised by the package.

-Jamie

|||

Jamie,

I guess I was looking at the architecture wrong. I thought the child package was the container for all other containers in the child package and therefore, by setting Propagate to false for all child package event handlers, no events would be raised by any containers in the child package to the parent package. That doesn't seem to be the case. By creating empty event handlers for the Execute Package Task in the parent package and setting Propagate to false for the empty event handlers, events raised by child package containers are not propagated to the parent package event handlers.

We are logging to two tables. Package events in one table and tasks in another table and have created a package template to handle the plumbing. This is great stuff.

|||

Martin Mason wrote:

Jamie,

I guess I was looking at the architecture wrong. I thought the child package was the container for all other containers in the child package and therefore, by setting Propagate to false for all child package event handlers, no events would be raised by any containers in the child package to the parent package. That doesn't seem to be the case.

Yeah, System::Propogate can often be misunderstood - mainly due to the complexity of the container hierarchy. System::Propogate only stops events fired by the container that it is scoped to from propogating. It does not stop events fired by descendant containers from propogating.

Martin Mason wrote:

By creating empty event handlers for the Execute Package Task in the parent package and setting Propagate to false for the empty event handlers, events raised by child package containers are not propagated to the parent package event handlers.

I'm surprised that that is the case though. The package container and the TaskHost container on the Execute Package Task are no different from any other container and should behave the same way.

Martin Mason wrote:

We are logging to two tables. Package events in one table and tasks in another table and have created a package template to handle the plumbing. This is great stuff.

I agree. I'm a big fan of using eventhandlers for custom logging and have advocated it strongly here: http://blogs.conchango.com/jamiethomson/archive/2005/06/11/1593.aspx

-Jamie

|||

Is there an easy way to identify which "System::Propogate" variable goes with what container object? The variable names and scope are all the same? How can you tell which variable goes with which container event. When I define an OnPreExecute event for multiple containers/tasks I can't tell which "System::Propogate" variable goes with what object?

Maybe I am missing something obvious but I do not see the connection?

Thanks!

|||

Each eventhandler has a [System::Propogate] variable scoped to it. Variables called [System::Propogate] are ONLY scoped to eventhandlers, nothing else. Therefore, when you use one there can be no ambiguity about which one you are using, it is the one scoped to the eventhandler you are currently editing.

And remember that an eventhandler is, in turn, scoped to a container in the control-flow.

Does that answer the question?

-Jamie

|||

Um Kind of.

I guess I should have noted that I was referring to the variables list, located under SSIS on the toolbar? Not just when I am editing the event. I understand that when I am editing the event ssis will only show me variables that are in scope to the event/container/task but I was referring to the "ALL" Variable list, where you can view all System and user variables and set their values etc. or add new variables or to view there properties in the properties pane?

Do I make sense?

Thanks!

Error Handling with Execute Package Task

I have a main package that calls several other packages using Execute Package Tasks. I also have OnPreExecute, OnPostExecute, and OnError event handlers at the package level to audit the beginning and completion of each package. I want to prevent each task from bubbling up to the package event handlers as well as prevent each task from bubbling up to the main package event handlers. I've tried setting the Propagate variable for each of the event handlers to False and setting the DisableEventHandlers property of each task to True but neither solution seems to work. Is there a way to do this that I'm missing?

You have to set [System::Propogate]=false in the eenthandler of the task for which you don't want events to propogate.

Your post doesn't specify on which eventhandlers you are setting this.

-Jamie

|||

I found another thread that describes the problem I'm seeing. Here is the previous thread and, in following the thread, I'm not sure if the conclusion was that this behavior was as designed or that this is really a bug. Here is a link to the previous discussion:

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=57523&SiteID=1

The problem in a nutshell is the following: There are two packages, a parent package which calls a child package using the Execute Package Task. Both packages have OnPostExecute event handlers defined at the package level to log progress with different ExecutionInstanceGUID. Even when the System::Propagate property is set to False for the child package OnPropagate event handler, the parent OnPostExecute event handler is still raised.

I guess the work around is to create an empty event handler for the Execute Package Task in the parent package and set the System::Propagate property for that empty event handler to False to prevent the main package OnPostExecute event from being raised. Since I have several Execute Package Tasks in the real solution, a better approach would be to wrap all the Execute Package Tasks in a Sequence container and create the do nothing event handler with the Propagate property set to false at the Sequence container rather than at each of the Execute Package tasks event handlers.

Does this make sense? Or is there possibly a better solution that I'm missing? Have to confess, I'm getting a bit overwhelmed by the number of possible appoaches one can use to log and audit package execution.

|||

Martin,

I cannot replicate your problem. If I set System::Propogate=FALSE on an eventhandler scoped to the child package then any events raised by the package container of the child package do not propogate to the parent package.

Note that this does NOT stop events raised by containers in the child package from propogating to the parent package. If you want to stop this from happening then set System::Propogate=FALSE on all of those containers as well.

I've also re-read your first post where you say "I want to prevent each task from bubbling up to the package event handlers ". If you only want to capture events fired by the package then you can compare System::PackageID to System::SourceID. If they are different then the event has not been raised by the package.

-Jamie

|||

Jamie,

I guess I was looking at the architecture wrong. I thought the child package was the container for all other containers in the child package and therefore, by setting Propagate to false for all child package event handlers, no events would be raised by any containers in the child package to the parent package. That doesn't seem to be the case. By creating empty event handlers for the Execute Package Task in the parent package and setting Propagate to false for the empty event handlers, events raised by child package containers are not propagated to the parent package event handlers.

We are logging to two tables. Package events in one table and tasks in another table and have created a package template to handle the plumbing. This is great stuff.

|||

Martin Mason wrote:

Jamie,

I guess I was looking at the architecture wrong. I thought the child package was the container for all other containers in the child package and therefore, by setting Propagate to false for all child package event handlers, no events would be raised by any containers in the child package to the parent package. That doesn't seem to be the case.

Yeah, System::Propogate can often be misunderstood - mainly due to the complexity of the container hierarchy. System::Propogate only stops events fired by the container that it is scoped to from propogating. It does not stop events fired by descendant containers from propogating.

Martin Mason wrote:

By creating empty event handlers for the Execute Package Task in the parent package and setting Propagate to false for the empty event handlers, events raised by child package containers are not propagated to the parent package event handlers.

I'm surprised that that is the case though. The package container and the TaskHost container on the Execute Package Task are no different from any other container and should behave the same way.

Martin Mason wrote:

We are logging to two tables. Package events in one table and tasks in another table and have created a package template to handle the plumbing. This is great stuff.

I agree. I'm a big fan of using eventhandlers for custom logging and have advocated it strongly here: http://blogs.conchango.com/jamiethomson/archive/2005/06/11/1593.aspx

-Jamie

|||

Is there an easy way to identify which "System::Propogate" variable goes with what container object? The variable names and scope are all the same? How can you tell which variable goes with which container event. When I define an OnPreExecute event for multiple containers/tasks I can't tell which "System::Propogate" variable goes with what object?

Maybe I am missing something obvious but I do not see the connection?

Thanks!

|||

Each eventhandler has a [System::Propogate] variable scoped to it. Variables called [System::Propogate] are ONLY scoped to eventhandlers, nothing else. Therefore, when you use one there can be no ambiguity about which one you are using, it is the one scoped to the eventhandler you are currently editing.

And remember that an eventhandler is, in turn, scoped to a container in the control-flow.

Does that answer the question?

-Jamie

|||

Um Kind of.

I guess I should have noted that I was referring to the variables list, located under SSIS on the toolbar? Not just when I am editing the event. I understand that when I am editing the event ssis will only show me variables that are in scope to the event/container/task but I was referring to the "ALL" Variable list, where you can view all System and user variables and set their values etc. or add new variables or to view there properties in the properties pane?

Do I make sense?

Thanks!

Error handling in cursor

I have cursor that loops through some records and calls a stored procedure. Sometimes the stored procedure raises an error. When an error is raised the cursor stops looping.

I would like the cursor to loop to the next record and continue executing the stored procedure. How do I implement this functionality? I suspect it has to do with using @.@.Error but I have limited experience with it. Thanks in advance.

Code Snippet

DECLARE PKIDs_Cursor CURSOR FOR

SELECT Id as PKID FROM Table1

OPEN PKIDs_Cursor;

DECLARE @.PKs VARCHAR(20)

FETCH NEXT FROM PKIDs_Cursor INTO @.PKs;

WHILE @.@.FETCH_STATUS = 0

BEGIN

EXEC dbo.spProcessInfo @.PKs, NULL;

FETCH NEXT FROM PKIDs_Cursor INTO @.PKs;

END;

CLOSE PKIDs_Cursor;

DEALLOCATE PKIDs_Cursor;

By default, SQL Server follows “ON ERROR RESUME NEXT”, that means when error occurs (if it is not critical error) it allows continuing to execute the next statement. Considering this statement your loop won’t break. You need not to use the @.@.ERROR here. If you want to force to discontinue the loop then only you need this variable.

Note:

In SQL Server 2000 you can’t suppers the error message thrown by the server. But the execution will continue.

If you use SQL Server 2005 then you can use the TRY..CATCH to suppress the error messages.

If you provide the error message it will be more helpful.

|||

Thank you for the reply Manivannan. I am using SQL Server 2000. The error message is a custom message raised by the stored procedure:

-2 Warning: Mapping failed - No actions taken.

“ON ERROR RESUME NEXT” behavior does not appear to be in effect. Any ideas?|||

What Severity Level you used on your Raiserror? Severity Level might affect the work-flow of your batch.

error handling flow

i've got a stored procedure (a) that calls another stored procedure
(b). inside b i become a deadlock victim and i die. how can i "catch"
this in a? using if @.@.error <> 0 in a doesn't seem to work. also, i'm
using sql server 2003 so no try/catch. thanks!
arthur
You're not using SQL Server 2003, since it doesn't exists. I assume a typo and you mean 2000.
You cannot catch a deadlock at the TSQL level. You have to do it in the client. This is one of the
nice things with TRY/CATCH in 2005, that you can catch a deadlock situation at the TSQL level.
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
Blog: http://solidqualitylearning.com/blogs/tibor/
"arthur" <alangham@.gmail.com> wrote in message
news:1138909906.663154.56220@.z14g2000cwz.googlegro ups.com...
> i've got a stored procedure (a) that calls another stored procedure
> (b). inside b i become a deadlock victim and i die. how can i "catch"
> this in a? using if @.@.error <> 0 in a doesn't seem to work. also, i'm
> using sql server 2003 so no try/catch. thanks!
> arthur
>
|||2000, right. thanks for clearing that up (not the 2000 part, the catch
part)!

error handling flow

i've got a stored procedure (a) that calls another stored procedure
(b). inside b i become a deadlock victim and i die. how can i "catch"
this in a? using if @.@.error <> 0 in a doesn't seem to work. also, i'm
using sql server 2003 so no try/catch. thanks!
arthurYou're not using SQL Server 2003, since it doesn't exists. I assume a typo and you mean 2000.
You cannot catch a deadlock at the TSQL level. You have to do it in the client. This is one of the
nice things with TRY/CATCH in 2005, that you can catch a deadlock situation at the TSQL level.
--
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
Blog: http://solidqualitylearning.com/blogs/tibor/
"arthur" <alangham@.gmail.com> wrote in message
news:1138909906.663154.56220@.z14g2000cwz.googlegroups.com...
> i've got a stored procedure (a) that calls another stored procedure
> (b). inside b i become a deadlock victim and i die. how can i "catch"
> this in a? using if @.@.error <> 0 in a doesn't seem to work. also, i'm
> using sql server 2003 so no try/catch. thanks!
> arthur
>|||2000, right. thanks for clearing that up (not the 2000 part, the catch
part)!

error handling flow

i've got a stored procedure (a) that calls another stored procedure
(b). inside b i become a deadlock victim and i die. how can i "catch"
this in a? using if @.@.error <> 0 in a doesn't seem to work. also, i'm
using sql server 2003 so no try/catch. thanks!
arthurYou're not using SQL Server 2003, since it doesn't exists. I assume a typo a
nd you mean 2000.
You cannot catch a deadlock at the TSQL level. You have to do it in the clie
nt. This is one of the
nice things with TRY/CATCH in 2005, that you can catch a deadlock situation
at the TSQL level.
Tibor Karaszi, SQL Server MVP
http://www.karaszi.com/sqlserver/default.asp
http://www.solidqualitylearning.com/
Blog: http://solidqualitylearning.com/blogs/tibor/
"arthur" <alangham@.gmail.com> wrote in message
news:1138909906.663154.56220@.z14g2000cwz.googlegroups.com...
> i've got a stored procedure (a) that calls another stored procedure
> (b). inside b i become a deadlock victim and i die. how can i "catch"
> this in a? using if @.@.error <> 0 in a doesn't seem to work. also, i'm
> using sql server 2003 so no try/catch. thanks!
> arthur
>|||2000, right. thanks for clearing that up (not the 2000 part, the catch
part)!