views:

844

answers:

5

When we can catch an exception like: Violation of UNIQUE KEY constraint 'IX_Product'. Cannot insert duplicate key in object 'Product'. (2627).
The challenge is how to dechiper the Index Name IX_Product as a Member (i.e. I don't want to substring out the message). There could be more than one unique constraint on a table and we would need to know which one to give more detailed information to the user. It would be preferable to catch it as DbException so it isn't SQL Server specific. Is there a way to get the affected index from the exception without having to parse the string?

The only solution I have came up with but I have not tested would to use a stored procedure and trap the error in there and returned the more detailed message from the stored procedure. But I believe this would still have issues.

+1  A: 

uh...maybe i'm missing something obvious...but wouldn't it be a better use of your time to fix the bug instead of parsing the exception?

Steven A. Lowe
In this case it is not a bug. The user entered data that violates a database constraint. I need to give them the correct information so that they can correct what they entered and try again. This is more of a validation issue not an error.
@Kay: LOL! Yes, that is still a bug. Users should never see database exceptions, and if you find yourself parsing database exceptions to present them to the user then pretty clearly you have overlooked some input validation rules. Fix the missing validation instead.
Steven A. Lowe
@Steven, How do you know what business logic this particular application has encoded into database constraints? ... And the gentleman's objective is to PREVENT the user from seeing the raw database exception...
Charles Bretana
@Steven, No it is not a 'bug' (error). If you have a name varchar(20) UNIQUE NOT NULL, then the user might try to enter a 'James' after one is already entered. Even if the system checks first it is still possible to violate the constraint with race conditions.
Arthur Thomas
@[Charles Bretana]: because he just told me, in the comment. He's not trying to prevent the user from seeing the db exception, he's trying to parse the db exception to present the info in more detail. Instead of checking for the violation in validation in the first place.
Steven A. Lowe
@[Arthur Thomas]: yes, this is a bug, in particular it is a missing validation. And your race condition argument is a red herring - the odds of a race condition for your example in a normal system are vanishingly small.
Steven A. Lowe
So when it does happen, however unlikely, it should throw a big nasty error instead of parsing some db exception? I would rather write a few more lines of code to be sure. Also I can let the db tell me that their was a dupe instead of checking manually. I just don't think there is an absolute way
Arthur Thomas
@[Arthur Thomas]: how much time do you spend on unlikely db exceptions? do you write exception-parsing code for deadlock exceptions? for connection-lost exceptions? for every possible constraint violation? This looks like we're doing a lot of extra work just to avoid doing an obvious validation. ;-)
Steven A. Lowe
@Steven, You are apparently speaking in a diferent dialect of English than the rest of us.... "parsing the exception to present the info.... " IS preventing the user from [directly] seeing the exception....
Charles Bretana
@Steven, IN the SAME comment he specifically said this is not a data input validation issue...
Charles Bretana
@Charles: LOL! directly yes, but he's doing that instead of the implied validation.
Steven A. Lowe
@Charles: "he specifically said this is not a data input validation issue"; I know. He's wrong, it is clearly a data input validation issue. ;-) How is "the product key must be unique" NOT a validation issue? This is a business rule, in a data-entry context, which is not being proactively validated.
Steven A. Lowe
@[Charles Bretana]: think about it this way - do you validate required field data-entry, or do you wait until the database throws a 'field cannot be null' exception? This situation is no different.
Steven A. Lowe
@Steven, He said that was an example.... not the specific problem... He said " ... an exception 'LIKE': Violation of UNIQUE KEY constraint ... ". I took his question to be about constraints in general, not about that specific constraint...
Charles Bretana
@[Charles Bretana]: and your answer is good, but he's solving the wrong problem. ;-)
Steven A. Lowe
@Steven, I agree with your underlying point, (that when possible, it's always better to validate user input at the UI than to let it get back to the DB) - but disagree that this user's question can be known absolutely (just cause it's a Unuiqe constraint) to be in that category. I mean, (con't)
Charles Bretana
almost every system (SO Included) exhibits an obvious example of one case where free-form user input must be unique and yet cannot (reasonably) be validated without butting up against the database constraint... the selection of a userID
Charles Bretana
@[Charles Bretana]: he said "There could be more than one unique constraint on a table and we would need to know which one to give more detailed information to the user" which strongly indicates the category of constraint. Besides, if the database can validate the constraint, then so can you!
Steven A. Lowe
@Joel, of course, anything is possible, but that doesn't make it smart... e.g., Validating a new-user-specified Login Id has not already been chosen by another user CAN be done in UI validation, but that would be the least preferable approach to take. Your "one size fits all" is - the wrong size.
Charles Bretana
@[Charles Bretana]: who is Joel? I can't see any Joel here... ;-)
Steven A. Lowe
@Steven, sorry!, Right thread, wrong UserId [grin] and, perhaps a good note on which to politely end our discussion! As is usual when thoughtful people disagree, we seem to have narrowed our points of disagreement to where it hardly seems worth the effort invested !
Charles Bretana
@[Charles Bretana]: LOL! In reality we probably do not disagree in general about the correct approach. I presume that you actually do at least some validation in the UI and you can rest assured that I also capture database constraint violations. Have a Happy New Year!
Steven A. Lowe
+4  A: 

You'll have to either:

  1. code your client component to recognize the constraint names that each insert/update statement might throw exceptions for,
  2. rename all your constraints so that they are "decipherable" in the way you want to use them in client code, or...
  3. check all the contraints in a stored proc before attempting the insert/update, and throw (Raise) your own custom exception in the proc if the check fails, BEFORE attempting the insert update and letting the contraint create the exception...
Charles Bretana
an excellent solution - for the wrong problem ;-)
Steven A. Lowe
A: 

Once you have it as an Exception object parsing is your best option. I wouldn't be too quick to dismiss it as an implementation though -- regular expressions with a group shouldn't be too hard to perfect for your situation.

You may also end up with a similar solution (parsing) in your stored proc as well. Also, by pushing the parsing code to the database server, you are forcing your databases to have the ability to resolve the exact details without parsing (it may be trivial on database A but exceptionally difficult on databases B & C).

Austin Salonen
+1  A: 

This sounds like a poor design issue. RDBMS should be enforcing these things, but the application should also be aware of, and built around, these constraints as well. It's a pretty brutal thing to expect your RBDMS to be handling logic exceptions that your application should be trapping or preventing to begin with. Database engines are for data operations, not for throwing exceptions to the application.

andrewbadera
unique is a constraint that you aren't aware of until you hit the db. You can do a check first but it is possible for someone to insert after the check.
Arthur Thomas
Sure, but again, this shouldn't happen. If you have a uniqueness issue to worry about, there should be a simple cache at the application level for just this sort of thing. You shouldn't be trying to parse database exception messages, period.
andrewbadera
A: 

Don't parse exception text. (echoing andrew here...)

If you're expecting a number of possible pitfalls in data insert/update actions, you should trap for those in your C# layer. Extend from ApplicationException to build your own exceptions to handle specific constraints like these.

But this assumes your data model is positioned such that you can make those determinations without having to use the db to tell you that a statement can be successfully executed. If your data design doesn't allow you to know if you could be violating constraints without running it through the db engine, there's a flaw in your data design.

jro