Groups | Blog | Home
all groups > dotnet distributed apps > november 2004 >

dotnet distributed apps : Exception handling in distributed ntier app



Gai
11/25/2004 8:30:53 PM
Hey all,

I'm building a distributed app in an NTier architecture (UI, BL, DA etc').
My client is a .Net Web Application and i'm using the Exception handling
application block.

I'm trying to establish an exception handling standard in which I don't need
to write Try and Catch blocks everywhere.

I'm aware of the option of propegating the errors to the Appliction_Error
handler, but I'm wondering if this is a good approach.

My questions are:
1. Should I add Exception handlers in any/all of my tiers? or just let the
Application_Error catch the errors?
2. If not what excpetions to intercept? SqlExceptions etc'...
3. Should the UI layer wrapp each BL call with Try Catch blocks? what else
should be wrapped?
4. Should I wrapp only INSERT, UPDATE, DELETE actions and not SELECT?

I should say that i'm intending to catch certin SqlExceptions, such as
UNIQUE constraints thrown from the DB, not query each time before
I UPADTE/INSERT a record, and translate the message to the user according to
a DB error bank.

I've been reading alot and haven't found any strict answers on what is the
best practice to do so is. I realize that there isn't a single
answer to my question, or a specific way to go by, but I trying to
understand what is the best way to handle it in an architecural manner.

As said above, I don't want to add exception handlers everywhere if I don't
need to.

I know it's long, but help would be much appreciated.

Thanks, Gai.



richlm
11/25/2004 10:35:39 PM
"Exception Management Architecture Guide" from Microsoft patterns and
practices contains most (if not all) of the useful best practices I am aware
of in relation to structured exception handling. It's an excellent general
reference.

You can find it here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/exceptdotnet.asp

If you are using the application block maybe you have already looked at
this? Perhaps you're looking for something more specific?

I think the guide provides answers to your questions 1-3, but here's my
interpretation/view:
1. Only if it makes sense. Do you need to log or audit it at the server?
Does it matter if it gets lost on the way from server to client? Is it
relevant to show it to the user? Can the server recover without bothering
the user? Do you need to add some context before passing it to the client?
2. Again - only catch a specific exception if you can do something useful
with it
3. It probably depends on whether you need to handle the exception as a
special case. If a global exception handler can do the job, why clutter your
UI logic with exception handling.

4. This sounds like TOO fine a level of detail for exception handling. You
should not use exception handling to implement business logic, and I have a
sneaky suspicion that's what you might be trying to do here when you are
talking about "constraints" and "translate the message to the user". The
user doesn't give a damn about constraints! In a really good architecture
(and UI design) the user should rarely (never?) be able to do something that
causes an exception.

No you certainly don't want to end up with try catch blocks all over the
place. Read the guide referenced above several times until you have the
basic principles there implanted in your subconscious...

Hope this helps.
Richard.

Gai
11/26/2004 11:51:59 AM
Thanks Richard, i'll do that.

[quoted text, click to view]

PJ
11/26/2004 12:21:40 PM
Good Day.

Sorry to interject, but I was thinking about implementing RAISERROR within
my sprocs for things like ForeignKey constraints & CHECK Constraints.
RAISERROR would have thrown an exception with my own unique error number,
thus enabling me to handle any problems for example -:

Event Foreign Key Constraint: 'The Supplier chosen may have been deleted."
Event CHECK Constarint: 'Please specifiy a Supplier Type between 1 & 3'.

OK, the last error could actually be handled in the BL layer but I dont want
my application to show a general error message that could quite possible
relate to any number of named constraints.

Would you set up your database using Declarative Referential Integrity as a
failsafe method but use the BL layer to check for these constraints prior to
Inserting, Updating & Deleting?

If the answer is yes then would you execute the statements as individual
transactions, i.e.

BLObjMethod_InsertSupplierProduct
{
BLmethod_ValidateSupplierTypeRange(...);
DALmethod_CheckSupplierExists(...); <-- DB access required.
DALmethod_CheckProductTypeExists(...); <-- DB access required.
...
}

or would you attempt to control the transactions from the BL layer, i.e.

BLObjMethod_InsertSupplierProduct
{
BLmethod_ValidateSupplierTypeRange(...);

DALmethodBeginTrans();
DALmethod_CheckSupplierExists(...); <-- DB access required.
DALmethod_CheckProductTypeExists(...); <-- DB access required.
DALmethodEndTrans();
...
}

or would you make your DAL a bit more intelligent, i.e.
DALObjMethod_InsertSupplierProduct
{
methodBeginTrans();
method_CheckSupplierExists(...); <-- DB access required.
method_CheckProductTypeExists(...); <-- DB access required.
methodEndTrans();
...
}

I hope the above makes some sense and your answers would be greatly
appreciated.
Just like Gai it seems hard to find definitive answers or the 'Very Best of
Practices'.

Kind Regards
Paul Johnson.



[quoted text, click to view]

richlm
11/26/2004 11:11:42 PM
Good points Paul!

RAISERROR makes me think of assembly language, VB3.0, GOTO and line numbers.
It is just so primitive.
Choose the language and platform that is appropriate for the job.

If you really do need to distinguish between different types of constraint
violation in the database AND you need to handle them specifically in your
application code, then maybe it's justified to use RAISEERROR. Use it if you
have some chance of recovering from the situation.

If all you need to do is log it and tell the user it didn't work there is no
point. There should be sufficient text in the SqlException to identify what
the problem was.

"Hitting' the database used to be considered costly in terms of performance,
but I don't believe that is longer the case.
Let the database do what it is there for - let it tell you a constraint was
violated and handle it where you feel most comfortable - for me that's in my
C# code.
I also want all my business logic in one place - I don't want it in the
database since I'm a C# developer.

I could go on on this topic but I think I'll leave it here....

Richard.

AddThis Social Bookmark Button