How can I catch UniqueKey Violation exceptions with EF6 and SQL Server? - c#

One of my tables have a unique key and when I try to insert a duplicate record it throws an exception as expected. But I need to distinguish unique key exceptions from others, so that I can customize the error message for unique key constraint violations.
All the solutions I've found online suggests to cast ex.InnerException to System.Data.SqlClient.SqlException and check the if Number property is equal to 2601 or 2627 as follows:
try
{
_context.SaveChanges();
}
catch (Exception ex)
{
var sqlException = ex.InnerException as System.Data.SqlClient.SqlException;
if (sqlException.Number == 2601 || sqlException.Number == 2627)
{
ErrorMessage = "Cannot insert duplicate values.";
}
else
{
ErrorMessage = "Error while saving data.";
}
}
But the problem is, casting ex.InnerException to System.Data.SqlClient.SqlException causes invalid cast error since ex.InnerException is actually type of System.Data.Entity.Core.UpdateException, not System.Data.SqlClient.SqlException.
What is the problem with the code above? How can I catch Unique Key Constraint violations?

With EF6 and the DbContext API (for SQL Server), I'm currently using this piece of code:
try
{
// Some DB access
}
catch (Exception ex)
{
HandleException(ex);
}
public virtual void HandleException(Exception exception)
{
if (exception is DbUpdateConcurrencyException concurrencyEx)
{
// A custom exception of yours for concurrency issues
throw new ConcurrencyException();
}
else if (exception is DbUpdateException dbUpdateEx)
{
if (dbUpdateEx.InnerException != null
&& dbUpdateEx.InnerException.InnerException != null)
{
if (dbUpdateEx.InnerException.InnerException is SqlException sqlException)
{
switch (sqlException.Number)
{
case 2627: // Unique constraint error
case 547: // Constraint check violation
case 2601: // Duplicated key row error
// Constraint violation exception
// A custom exception of yours for concurrency issues
throw new ConcurrencyException();
default:
// A custom exception of yours for other DB issues
throw new DatabaseAccessException(
dbUpdateEx.Message, dbUpdateEx.InnerException);
}
}
throw new DatabaseAccessException(dbUpdateEx.Message, dbUpdateEx.InnerException);
}
}
// If we're here then no exception has been thrown
// So add another piece of code below for other exceptions not yet handled...
}
As you mentioned UpdateException, I'm assuming you're using the ObjectContext API, but it should be similar.

In my case, I'm using EF 6 and decorated one of the properties in my model with:
[Index(IsUnique = true)]
To catch the violation I do the following, using C# 7, this becomes much easier:
protected async Task<IActionResult> PostItem(Item item)
{
_DbContext.Items.Add(item);
try
{
await _DbContext.SaveChangesAsync();
}
catch (DbUpdateException e)
when (e.InnerException?.InnerException is SqlException sqlEx &&
(sqlEx.Number == 2601 || sqlEx.Number == 2627))
{
return StatusCode(StatusCodes.Status409Conflict);
}
return Ok();
}
Note, that this will only catch unique index constraint violation.

try
{
// do your insert
}
catch(Exception ex)
{
if (ex.GetBaseException().GetType() == typeof(SqlException))
{
Int32 ErrorCode = ((SqlException)ex.InnerException).Number;
switch(ErrorCode)
{
case 2627: // Unique constraint error
break;
case 547: // Constraint check violation
break;
case 2601: // Duplicated key row error
break;
default:
break;
}
}
else
{
// handle normal exception
}
}

// put this block in your loop
try
{
// do your insert
}
catch(SqlException ex)
{
// the exception alone won't tell you why it failed...
if(ex.Number == 2627) // <-- but this will
{
//Violation of primary key. Handle Exception
}
}
EDIT:
You could also just inspect the message component of the exception. Something like this:
if (ex.Message.Contains("UniqueConstraint")) // do stuff

I thought it might be useful to show some code not only handling the duplicate row exception but also extracting some useful information that could be used for programmatic purposes. E.g. composing a custom message.
This Exception subclass uses regex to extract the db table name, index name, and key values.
public class DuplicateKeyRowException : Exception
{
public string TableName { get; }
public string IndexName { get; }
public string KeyValues { get; }
public DuplicateKeyRowException(SqlException e) : base(e.Message, e)
{
if (e.Number != 2601)
throw new ArgumentException("SqlException is not a duplicate key row exception", e);
var regex = #"\ACannot insert duplicate key row in object \'(?<TableName>.+?)\' with unique index \'(?<IndexName>.+?)\'\. The duplicate key value is \((?<KeyValues>.+?)\)";
var match = new System.Text.RegularExpressions.Regex(regex, System.Text.RegularExpressions.RegexOptions.Compiled).Match(e.Message);
Data["TableName"] = TableName = match?.Groups["TableName"].Value;
Data["IndexName"] = IndexName = match?.Groups["IndexName"].Value;
Data["KeyValues"] = KeyValues = match?.Groups["KeyValues"].Value;
}
}
The DuplicateKeyRowException class is easy enough to use... just create some error handling code like in previous answers...
public void SomeDbWork() {
// ... code to create/edit/update/delete entities goes here ...
try { Context.SaveChanges(); }
catch (DbUpdateException e) { throw HandleDbUpdateException(e); }
}
public Exception HandleDbUpdateException(DbUpdateException e)
{
// handle specific inner exceptions...
if (e.InnerException is System.Data.SqlClient.SqlException ie)
return HandleSqlException(ie);
return e; // or, return the generic error
}
public Exception HandleSqlException(System.Data.SqlClient.SqlException e)
{
// handle specific error codes...
if (e.Number == 2601) return new DuplicateKeyRowException(e);
return e; // or, return the generic error
}

If you want to catch unique constraint
try {
// code here
}
catch(Exception ex) {
//check for Exception type as sql Exception
if(ex.GetBaseException().GetType() == typeof(SqlException)) {
//Violation of primary key/Unique constraint can be handled here. Also you may //check if Exception Message contains the constraint Name
}
}

You have to be very specific while writing the code.
try
{
// do your stuff here.
{
catch (Exception ex)
{
if (ex.Message.Contains("UNIQUE KEY"))
{
Master.ShowMessage("Cannot insert duplicate Name.", MasterSite.MessageType.Error);
}
else { Master.ShowMessage(ex.Message, MasterSite.MessageType.Error); }
}
I have just updated the above code a bit and its working for me.

Related

Net5 mysql Access Duplicate ErrorCode

I'm trying to show a Duplicate Record error message in an WebAPI service. I'm using .net5 and mysql. I cannot seem to find a way to pull the duplicateEntry message from the exception response. I'd like to key in on the ErrorCode field and use this to tailor a response to the user. I can see the Message property, but cannot figure out how to access the innerException.
{
try
{
module.Id = Guid.NewGuid();
await _moduleRepository.Add(module);
await _uow.CompleteAsync();
return true;
}
catch (DbUpdateException ex)
{
logger.LogWarning("Module - Add Error: " + ex.Message);
return false;
}
}
You may try to catch an Exception object which has a InnerException attribute. Also, you may also check DbEntityValidationException class.
Reference: link
Found something that worked. Made a helper function, but this is highly coupled to Mysql. Had to check the InnerException to see if it was of type MsyqlException.
{
public static string GetExceptionMessage(Exception ex)
{
var message = ex.Message;
var innerException = ex.InnerException;
if (innerException != null && (innerException.GetType() == typeof(MySqlException)))
{
var dbException = (MySqlException)innerException;
if(dbException.ErrorCode == MySqlErrorCode.DuplicateKeyEntry)
{
return ErrorMessages.RecordExists;
} else
{
return ErrorMessages.UnknownError;
}
}
return message;
}
}

How to handle Unique Key Constraint in Insert or Update? [duplicate]

I want to know how we identify the primary key duplication error from SQL Server error code in C#.
As a example, I have a C# form to enter data into a SQL Server database, when an error occurs while data entry, how can I identify the reason for the error from the exception?
If you catch SqlException then see its number, the number 2627 would mean violation of unique constraint (including primary key).
try
{
// insertion code
}
catch (SqlException ex)
{
if (ex.Number == 2627)
{
//Violation of primary key. Handle Exception
}
else throw;
}
MSSQL_ENG002627
This is a general error that can be raised regardless of whether a
database is replicated. In replicated databases, the error is
typically raised because primary keys have not been managed appropriately across the topology.
This is an old thread but I guess it's worth noting that since C#6 you can:
try
{
await command.ExecuteNonQueryAsync(cancellation);
}
catch (SqlException ex) when (ex.Number == 2627)
{
// Handle unique key violation
}
And with C#7 and a wrapping exception (like Entity Framework Core):
try
{
await _context.SaveChangesAsync(cancellation);
}
catch (DbUpdateException ex)
when ((ex.InnerException as SqlException)?.Number == 2627)
{
// Handle unique key violation
}
The biggest advantage of this approach in comparison with the accepted answer is:
In case the error number is not equal to 2627 and hence, it's not a unique key violation, the exception is not caught.
Without the exception filter (when) you'd better remember re-throwing that exception in case you can't handle it. And ideally not to forget to use ExceptionDispatchInfo so that the original stack is not lost.
In case of Entity Framework, the accepted answer won't work and the error will end up not being caught. Here is a test code, only the entity catch statement will be hit or of course the generic exception if entity statement removed:
try
{
db.InsertProcedureCall(id);
}
catch (SqlException e0)
{
// Won't catch
}
catch (EntityCommandExecutionException e1)
{
// Will catch
var se = e1.InnerException as SqlException;
var code = se.Number;
}
catch (Exception e2)
{
// if the Entity catch is removed, this will work too
var se = e2.InnerException as SqlException;
var code = se.Number;
}
Working code for filter only duplicate primary key voilation exception
using System.Data.Entity.Infrastructure;
using System.Data.SqlClient;
.........
try{
abc...
}
catch (DbUpdateException ex)
{
if (ex.InnerException.InnerException is SqlException sqlEx && sqlEx.Number == 2601)
{
return ex.ToString();
}
else
{
throw;
}
}
Note fine detial :- ex.InnerException.InnerException not ex.InnerException

Code does not catch FormatException in C#

I have the following method in the class ProductServices:
public bool IsDownloadAllowed(int Id, string productId)
{
if (CustomStringFunctions.IsGuid(productId))
{
//Do Something
}
else
{
throw new FormatException("The Guid must be a valid Guid!");
}
}
If I use the method in the following set of instructions:
var _productServices = new ProductServices();
try
{
var flag = _productServices.IsDownloadAllowed(Id, productId);
//do something
}
catch (Exception e)
{
//handle exception
}
The exception is not caught by the catch statement. I also tried to replace Exception with FormatException with no luck. What am I doing wrong?
You must have mute exception in this code
if (CustomStringFunctions.IsGuid(productId))
{
//Do Something
}
You must be sure that you throw exception when occured (In the Do Something)
Sample of mute exception
Try
{
}
Catch(Exception ex)
{
//throw don't exist
}
Your code looks correct. A possible explanation for your problem is that CustomStringFunctions.IsGuid is incorrectly returning true, so the \\do something branch is executing instead of the exception-throwing branch.

How can I know if an SQLexception was thrown because of foreign key violation?

I want to tell the user that a record was not deleted because it has child data, but how can I be sure that the exception was thrown because of a foreign key violation? I see that there a sqlexception class that is used for all sql exception.
Assume you're using SQL Server.
Using teh web archive - https://web.archive.org/web/20190120182351/https://blogs.msdn.microsoft.com/tomholl/2007/08/01/mapping-sql-server-errors-to-net-exceptions-the-fun-way/
try
{
# SQL Stuff
}
catch (SqlException ex)
{
if (ex.Errors.Count > 0) // Assume the interesting stuff is in the first error
{
switch (ex.Errors[0].Number)
{
case 547: // Foreign Key violation
throw new InvalidOperationException("Some helpful description", ex);
break;
case 2601: // Primary key violation
throw new DuplicateRecordException("Some other helpful description", ex);
break;
default:
throw new DataAccessException(ex);
}
}
}
Case 547 is your man.
UPDATE The above is sample code and should not be used. Please follow the link as to explain why.
You can write your exception-expected code in the Try block if any exception will be thrown it will be catch further now you can get error number.now can check is it a Foreign Key violation or not
try
{
//your deletetion code
}catch (SqlException ex)
{
if (ex.Errors.Count > 0) // Assume the interesting stuff is in the first error
{
switch (ex.Errors[0].Number)
{
case 547: // Foreign Key violation
lblError.Text = "Cannot Delete this Record this is associated with other record...!";
break;
default:
throw;
}
}
}

Catch multiple exceptions at once?

It is discouraged to simply catch System.Exception. Instead, only the "known" exceptions should be caught.
Now, this sometimes leads to unnecessary repetitive code, for example:
try
{
WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
WebId = Guid.Empty;
}
catch (OverflowException)
{
WebId = Guid.Empty;
}
I wonder: Is there a way to catch both exceptions and only call the WebId = Guid.Empty call once?
The given example is rather simple, as it's only a GUID. But imagine code where you modify an object multiple times, and if one of the manipulations fails expectedly, you want to "reset" the object. However, if there is an unexpected exception, I still want to throw that higher.
Catch System.Exception and switch on the types
catch (Exception ex)
{
if (ex is FormatException || ex is OverflowException)
{
WebId = Guid.Empty;
return;
}
throw;
}
EDIT: I do concur with others who are saying that, as of C# 6.0, exception filters are now a perfectly fine way to go: catch (Exception ex) when (ex is ... || ex is ... )
Except that I still kind of hate the one-long-line layout and would personally lay the code out like the following. I think this is as functional as it is aesthetic, since I believe it improves comprehension. Some may disagree:
catch (Exception ex) when (
ex is ...
|| ex is ...
|| ex is ...
)
ORIGINAL:
I know I'm a little late to the party here, but holy smoke...
Cutting straight to the chase, this kind of duplicates an earlier answer, but if you really want to perform a common action for several exception types and keep the whole thing neat and tidy within the scope of the one method, why not just use a lambda/closure/inline function to do something like the following? I mean, chances are pretty good that you'll end up realizing that you just want to make that closure a separate method that you can utilize all over the place. But then it will be super easy to do that without actually changing the rest of the code structurally. Right?
private void TestMethod ()
{
Action<Exception> errorHandler = ( ex ) => {
// write to a log, whatever...
};
try
{
// try some stuff
}
catch ( FormatException ex ) { errorHandler ( ex ); }
catch ( OverflowException ex ) { errorHandler ( ex ); }
catch ( ArgumentNullException ex ) { errorHandler ( ex ); }
}
I can't help but wonder (warning: a little irony/sarcasm ahead) why on earth go to all this effort to basically just replace the following:
try
{
// try some stuff
}
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}
...with some crazy variation of this next code smell, I mean example, only to pretend that you're saving a few keystrokes.
// sorta sucks, let's be honest...
try
{
// try some stuff
}
catch( Exception ex )
{
if (ex is FormatException ||
ex is OverflowException ||
ex is ArgumentNullException)
{
// write to a log, whatever...
return;
}
throw;
}
Because it certainly isn't automatically more readable.
Granted, I left the three identical instances of /* write to a log, whatever... */ return; out of the first example.
But that's sort of my point. Y'all have heard of functions/methods, right? Seriously. Write a common ErrorHandler function and, like, call it from each catch block.
If you ask me, the second example (with the if and is keywords) is both significantly less readable, and simultaneously significantly more error-prone during the maintenance phase of your project.
The maintenance phase, for anyone who might be relatively new to programming, is going to compose 98.7% or more of the overall lifetime of your project, and the poor schmuck doing the maintenance is almost certainly going to be someone other than you. And there is a very good chance they will spend 50% of their time on the job cursing your name.
And of course FxCop barks at you and so you have to also add an attribute to your code that has precisely zip to do with the running program, and is only there to tell FxCop to ignore an issue that in 99.9% of cases it is totally correct in flagging. And, sorry, I might be mistaken, but doesn't that "ignore" attribute end up actually compiled into your app?
Would putting the entire if test on one line make it more readable? I don't think so. I mean, I did have another programmer vehemently argue once long ago that putting more code on one line would make it "run faster." But of course he was stark raving nuts. Trying to explain to him (with a straight face--which was challenging) how the interpreter or compiler would break that long line apart into discrete one-instruction-per-line statements--essentially identical to the result if he had gone ahead and just made the code readable instead of trying to out-clever the compiler--had no effect on him whatsoever. But I digress.
How much less readable does this get when you add three more exception types, a month or two from now? (Answer: it gets a lot less readable).
One of the major points, really, is that most of the point of formatting the textual source code that we're all looking at every day is to make it really, really obvious to other human beings what is actually happening when the code runs. Because the compiler turns the source code into something totally different and couldn't care less about your code formatting style. So all-on-one-line totally sucks, too.
Just saying...
// super sucks...
catch( Exception ex )
{
if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
{
// write to a log, whatever...
return;
}
throw;
}
As others have pointed out, you can have an if statement inside your catch block to determine what is going on. C#6 supports Exception Filters, so the following will work:
try { … }
catch (Exception e) when (MyFilter(e))
{
…
}
The MyFilter method could then look something like this:
private bool MyFilter(Exception e)
{
return e is ArgumentNullException || e is FormatException;
}
Alternatively, this can be all done inline (the right hand side of the when statement just has to be a boolean expression).
try { … }
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
…
}
This is different from using an if statement from within the catch block, using exception filters will not unwind the stack.
You can download Visual Studio 2015 to check this out.
If you want to continue using Visual Studio 2013, you can install the following nuget package:
Install-Package Microsoft.Net.Compilers
At time of writing, this will include support for C# 6.
Referencing this package will cause the project to be built using the
specific version of the C# and Visual Basic compilers contained in the
package, as opposed to any system installed version.
Not in C# unfortunately, as you'd need an exception filter to do it and C# doesn't expose that feature of MSIL. VB.NET does have this capability though, e.g.
Catch ex As Exception When TypeOf ex Is FormatException OrElse TypeOf ex Is OverflowException
What you could do is use an anonymous function to encapsulate your on-error code, and then call it in those specific catch blocks:
Action onError = () => WebId = Guid.Empty;
try
{
// something
}
catch (FormatException)
{
onError();
}
catch (OverflowException)
{
onError();
}
Exception filters are now available in c# 6+. You can do
try
{
WebId = new Guid(queryString["web"]);
}
catch (Exception ex) when(ex is FormatException || ex is OverflowException)
{
WebId = Guid.Empty;
}
In C# 7.0+, you can combine this with pattern matching too
try
{
await Task.WaitAll(tasks);
}
catch (Exception ex) when( ex is AggregateException ae &&
ae.InnerExceptions.Count > tasks.Count/2)
{
//More than half of the tasks failed maybe..?
}
For the sake of completeness, since .NET 4.0 the code can rewritten as:
Guid.TryParse(queryString["web"], out WebId);
TryParse never throws exceptions and returns false if format is wrong, setting WebId to Guid.Empty.
Since C# 7 you can avoid introducing a variable on a separate line:
Guid.TryParse(queryString["web"], out Guid webId);
You can also create methods for parsing returning tuples, which aren't available in .NET Framework yet as of version 4.6:
(bool success, Guid result) TryParseGuid(string input) =>
(Guid.TryParse(input, out Guid result), result);
And use them like this:
WebId = TryParseGuid(queryString["web"]).result;
// or
var tuple = TryParseGuid(queryString["web"]);
WebId = tuple.success ? tuple.result : DefaultWebId;
Next useless update to this useless answer comes when deconstruction of out-parameters is implemented in C# 12. :)
If you can upgrade your application to C# 6 you are lucky. The new C# version has implemented Exception filters. So you can write this:
catch (Exception ex) when (ex is FormatException || ex is OverflowException) {
WebId = Guid.Empty;
}
Some people think this code is the same as
catch (Exception ex) {
if (ex is FormatException || ex is OverflowException) {
WebId = Guid.Empty;
}
throw;
}
But it´s not. Actually this is the only new feature in C# 6 that is not possible to emulate in prior versions. First, a re-throw means more overhead than skipping the catch. Second, it is not semantically equivalent. The new feature preserves the stack intact when you are debugging your code. Without this feature the crash dump is less useful or even useless.
See a discussion about this on CodePlexNot available anymore. And an example showing the difference.
Update for C# 9
Using the new pattern matching enhancements made in C# 9, you can shorten the expression in the exception filter. Now, catching multiple exceptions is a simple is this:
try
{
WebId = new Guid(queryString["web"]);
}
catch (Exception e) when (e is FormatException or OverflowException)
{
WebId = Guid.Empty;
}
With C# 7 the answer from Michael Stum can be improved while keeping the readability of a switch statement:
catch (Exception ex)
{
switch (ex)
{
case FormatException _:
case OverflowException _:
WebId = Guid.Empty;
break;
default:
throw;
}
}
Thanks to Orace comment this can be simplified with C# 8 by omitting the discard variable:
catch (Exception ex)
{
switch (ex)
{
case FormatException:
case OverflowException:
WebId = Guid.Empty;
break;
default:
throw;
}
}
And with C# 8 as switch expression:
catch (Exception ex)
{
WebId = ex switch
{
_ when ex is FormatException || ex is OverflowException => Guid.Empty,
_ => throw ex
};
}
As Nechemia Hoffmann pointed out. The latter example will cause a loss of the stacktrace. This can be prevented by using the extension method described by Jürgen Steinblock to capture the stacktrace before throwing:
catch (Exception ex)
{
WebId = ex switch
{
_ when ex is FormatException || ex is OverflowException => Guid.Empty,
_ => throw ex.Capture()
};
}
public static Exception Capture(this Exception ex)
{
ExceptionDispatchInfo.Capture(ex).Throw();
return ex;
}
Both styles can be simplified with the pattern matching enhancements of C# 9:
catch (Exception ex)
{
switch (ex)
{
case FormatException or OverflowException:
WebId = Guid.Empty;
break;
default:
throw;
}
}
catch (Exception ex)
{
WebId = ex switch
{
_ when ex is FormatException or OverflowException => Guid.Empty,
_ => throw ex.Capture()
};
}
If you don't want to use an if statement within the catch scopes, in C# 6.0 you can use Exception Filters syntax which was already supported by the CLR in previews versions but existed only in VB.NET/MSIL:
try
{
WebId = new Guid(queryString["web"]);
}
catch (Exception exception) when (exception is FormatException || ex is OverflowException)
{
WebId = Guid.Empty;
}
This code will catch the Exception only when it's a InvalidDataException or ArgumentNullException.
Actually, you can put basically any condition inside that when clause:
static int a = 8;
...
catch (Exception exception) when (exception is InvalidDataException && a == 8)
{
Console.WriteLine("Catch");
}
Note that as opposed to an if statement inside the catch's scope, Exception Filters cannot throw Exceptions, and when they do, or when the condition is not true, the next catch condition will be evaluated instead:
static int a = 7;
static int b = 0;
...
try
{
throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
Console.WriteLine("General catch");
}
Output: General catch.
When there is more then one true Exception Filter - the first one will be accepted:
static int a = 8;
static int b = 4;
...
try
{
throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
Console.WriteLine("General catch");
}
Output: Catch.
And as you can see in the MSIL the code is not translated to if statements, but to Filters, and Exceptions cannot be throw from within the areas marked with Filter 1 and Filter 2 but the filter throwing the Exception will fail instead, also the last comparison value pushed to the stack before the endfilter command will determine the success/failure of the filter (Catch 1 XOR Catch 2 will execute accordingly):
Also, specifically Guid has the Guid.TryParse method.
catch (Exception ex) when (ex is FormatException or OverflowException)
{
WebId = Guid.Empty;
}
or
catch (Exception ex)
{
if (ex is not FormatException and not OverflowException)
throw;
WebId = Guid.Empty;
}
The accepted answer seems acceptable, except that CodeAnalysis/FxCop will complain about the fact that it's catching a general exception type.
Also, it seems the "is" operator might degrade performance slightly.
CA1800: Do not cast unnecessarily says to "consider testing the result of the 'as' operator instead", but if you do that, you'll be writing more code than if you catch each exception separately.
Anyhow, here's what I would do:
bool exThrown = false;
try
{
// Something
}
catch (FormatException) {
exThrown = true;
}
catch (OverflowException) {
exThrown = true;
}
if (exThrown)
{
// Something else
}
in C# 6 the recommended approach is to use Exception Filters, here is an example:
try
{
throw new OverflowException();
}
catch(Exception e ) when ((e is DivideByZeroException) || (e is OverflowException))
{
// this will execute iff e is DividedByZeroEx or OverflowEx
Console.WriteLine("E");
}
This is a variant of Matt's answer (I feel that this is a bit cleaner)...use a method:
public void TryCatch(...)
{
try
{
// something
return;
}
catch (FormatException) {}
catch (OverflowException) {}
WebId = Guid.Empty;
}
Any other exceptions will be thrown and the code WebId = Guid.Empty; won't be hit. If you don't want other exceptions to crash your program, just add this AFTER the other two catches:
...
catch (Exception)
{
// something, if anything
return; // only need this if you follow the example I gave and put it all in a method
}
Joseph Daigle's Answer is a good solution, but I found the following structure to be a bit tidier and less error prone.
catch(Exception ex)
{
if (!(ex is SomeException || ex is OtherException)) throw;
// Handle exception
}
There are a few advantages of inverting the expression:
A return statement is not necessary
The code isn't nested
There's no risk of forgetting the 'throw' or 'return' statements that in Joseph's solution are separated from the expression.
It can even be compacted to a single line (though not very pretty)
catch(Exception ex) { if (!(ex is SomeException || ex is OtherException)) throw;
// Handle exception
}
Edit:
The exception filtering in C# 6.0 will make the syntax a bit cleaner and comes with a number of other benefits over any current solution. (most notably leaving the stack unharmed)
Here is how the same problem would look using C# 6.0 syntax:
catch(Exception ex) when (ex is SomeException || ex is OtherException)
{
// Handle exception
}
#Micheal
Slightly revised version of your code:
catch (Exception ex)
{
Type exType = ex.GetType();
if (exType == typeof(System.FormatException) ||
exType == typeof(System.OverflowException)
{
WebId = Guid.Empty;
} else {
throw;
}
}
String comparisons are ugly and slow.
How about
try
{
WebId = Guid.Empty;
WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
}
catch (OverflowException)
{
}
Cautioned and Warned: Yet another kind, functional style.
What is in the link doesn't answer your question directly, but it's trivial to extend it to look like:
static void Main()
{
Action body = () => { ...your code... };
body.Catch<InvalidOperationException>()
.Catch<BadCodeException>()
.Catch<AnotherException>(ex => { ...handler... })();
}
(Basically provide another empty Catch overload which returns itself)
The bigger question to this is why. I do not think the cost outweighs the gain here :)
Update 2015-12-15: See https://stackoverflow.com/a/22864936/1718702 for C#6. It's a cleaner and now standard in the language.
Geared for people that want a more elegant solution to catch once and filter exceptions, I use an extension method as demonstrated below.
I already had this extension in my library, originally written for other purposes, but it worked just perfectly for type checking on exceptions. Plus, imho, it looks cleaner than a bunch of || statements. Also, unlike the accepted answer, I prefer explicit exception handling so ex is ... had undesireable behaviour as derrived classes are assignable to there parent types).
Usage
if (ex.GetType().IsAnyOf(
typeof(FormatException),
typeof(ArgumentException)))
{
// Handle
}
else
throw;
IsAnyOf.cs Extension (See Full Error Handling Example for Dependancies)
namespace Common.FluentValidation
{
public static partial class Validate
{
/// <summary>
/// Validates the passed in parameter matches at least one of the passed in comparisons.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_comparisons">Values to compare against.</param>
/// <returns>True if a match is found.</returns>
/// <exception cref="ArgumentNullException"></exception>
public static bool IsAnyOf<T>(this T p_parameter, params T[] p_comparisons)
{
// Validate
p_parameter
.CannotBeNull("p_parameter");
p_comparisons
.CannotBeNullOrEmpty("p_comparisons");
// Test for any match
foreach (var item in p_comparisons)
if (p_parameter.Equals(item))
return true;
// Return no matches found
return false;
}
}
}
Full Error Handling Example (Copy-Paste to new Console app)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common.FluentValidation;
namespace IsAnyOfExceptionHandlerSample
{
class Program
{
static void Main(string[] args)
{
// High Level Error Handler (Log and Crash App)
try
{
Foo();
}
catch (OutOfMemoryException ex)
{
Console.WriteLine("FATAL ERROR! System Crashing. " + ex.Message);
Console.ReadKey();
}
}
static void Foo()
{
// Init
List<Action<string>> TestActions = new List<Action<string>>()
{
(key) => { throw new FormatException(); },
(key) => { throw new ArgumentException(); },
(key) => { throw new KeyNotFoundException();},
(key) => { throw new OutOfMemoryException(); },
};
// Run
foreach (var FooAction in TestActions)
{
// Mid-Level Error Handler (Appends Data for Log)
try
{
// Init
var SomeKeyPassedToFoo = "FooParam";
// Low-Level Handler (Handle/Log and Keep going)
try
{
FooAction(SomeKeyPassedToFoo);
}
catch (Exception ex)
{
if (ex.GetType().IsAnyOf(
typeof(FormatException),
typeof(ArgumentException)))
{
// Handle
Console.WriteLine("ex was {0}", ex.GetType().Name);
Console.ReadKey();
}
else
{
// Add some Debug info
ex.Data.Add("SomeKeyPassedToFoo", SomeKeyPassedToFoo.ToString());
throw;
}
}
}
catch (KeyNotFoundException ex)
{
// Handle differently
Console.WriteLine(ex.Message);
int Count = 0;
if (!Validate.IsAnyNull(ex, ex.Data, ex.Data.Keys))
foreach (var Key in ex.Data.Keys)
Console.WriteLine(
"[{0}][\"{1}\" = {2}]",
Count, Key, ex.Data[Key]);
Console.ReadKey();
}
}
}
}
}
namespace Common.FluentValidation
{
public static partial class Validate
{
/// <summary>
/// Validates the passed in parameter matches at least one of the passed in comparisons.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_comparisons">Values to compare against.</param>
/// <returns>True if a match is found.</returns>
/// <exception cref="ArgumentNullException"></exception>
public static bool IsAnyOf<T>(this T p_parameter, params T[] p_comparisons)
{
// Validate
p_parameter
.CannotBeNull("p_parameter");
p_comparisons
.CannotBeNullOrEmpty("p_comparisons");
// Test for any match
foreach (var item in p_comparisons)
if (p_parameter.Equals(item))
return true;
// Return no matches found
return false;
}
/// <summary>
/// Validates if any passed in parameter is equal to null.
/// </summary>
/// <param name="p_parameters">Parameters to test for Null.</param>
/// <returns>True if one or more parameters are null.</returns>
public static bool IsAnyNull(params object[] p_parameters)
{
p_parameters
.CannotBeNullOrEmpty("p_parameters");
foreach (var item in p_parameters)
if (item == null)
return true;
return false;
}
}
}
namespace Common.FluentValidation
{
public static partial class Validate
{
/// <summary>
/// Validates the passed in parameter is not null, throwing a detailed exception message if the test fails.
/// </summary>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_name">Name of tested parameter to assist with debugging.</param>
/// <exception cref="ArgumentNullException"></exception>
public static void CannotBeNull(this object p_parameter, string p_name)
{
if (p_parameter == null)
throw
new
ArgumentNullException(
string.Format("Parameter \"{0}\" cannot be null.",
p_name), default(Exception));
}
}
}
namespace Common.FluentValidation
{
public static partial class Validate
{
/// <summary>
/// Validates the passed in parameter is not null or an empty collection, throwing a detailed exception message if the test fails.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_name">Name of tested parameter to assist with debugging.</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public static void CannotBeNullOrEmpty<T>(this ICollection<T> p_parameter, string p_name)
{
if (p_parameter == null)
throw new ArgumentNullException("Collection cannot be null.\r\nParameter_Name: " + p_name, default(Exception));
if (p_parameter.Count <= 0)
throw new ArgumentOutOfRangeException("Collection cannot be empty.\r\nParameter_Name: " + p_name, default(Exception));
}
/// <summary>
/// Validates the passed in parameter is not null or empty, throwing a detailed exception message if the test fails.
/// </summary>
/// <param name="p_parameter">Parameter to validate.</param>
/// <param name="p_name">Name of tested parameter to assist with debugging.</param>
/// <exception cref="ArgumentException"></exception>
public static void CannotBeNullOrEmpty(this string p_parameter, string p_name)
{
if (string.IsNullOrEmpty(p_parameter))
throw new ArgumentException("String cannot be null or empty.\r\nParameter_Name: " + p_name, default(Exception));
}
}
}
Two Sample NUnit Unit Tests
Matching behaviour for Exception types is exact (ie. A child IS NOT a match for any of its parent types).
using System;
using System.Collections.Generic;
using Common.FluentValidation;
using NUnit.Framework;
namespace UnitTests.Common.Fluent_Validations
{
[TestFixture]
public class IsAnyOf_Tests
{
[Test, ExpectedException(typeof(ArgumentNullException))]
public void IsAnyOf_ArgumentNullException_ShouldNotMatch_ArgumentException_Test()
{
Action TestMethod = () => { throw new ArgumentNullException(); };
try
{
TestMethod();
}
catch (Exception ex)
{
if (ex.GetType().IsAnyOf(
typeof(ArgumentException), /*Note: ArgumentNullException derrived from ArgumentException*/
typeof(FormatException),
typeof(KeyNotFoundException)))
{
// Handle expected Exceptions
return;
}
//else throw original
throw;
}
}
[Test, ExpectedException(typeof(OutOfMemoryException))]
public void IsAnyOf_OutOfMemoryException_ShouldMatch_OutOfMemoryException_Test()
{
Action TestMethod = () => { throw new OutOfMemoryException(); };
try
{
TestMethod();
}
catch (Exception ex)
{
if (ex.GetType().IsAnyOf(
typeof(OutOfMemoryException),
typeof(StackOverflowException)))
throw;
/*else... Handle other exception types, typically by logging to file*/
}
}
}
}
Note that I did find one way to do it, but this looks more like material for The Daily WTF:
catch (Exception ex)
{
switch (ex.GetType().Name)
{
case "System.FormatException":
case "System.OverflowException":
WebId = Guid.Empty;
break;
default:
throw;
}
}
Since I felt like these answers just touched the surface, I attempted to dig a bit deeper.
So what we would really want to do is something that doesn't compile, say:
// Won't compile... damn
public static void Main()
{
try
{
throw new ArgumentOutOfRangeException();
}
catch (ArgumentOutOfRangeException)
catch (IndexOutOfRangeException)
{
// ... handle
}
The reason we want this is because we don't want the exception handler to catch things that we need later on in the process. Sure, we can catch an Exception and check with an 'if' what to do, but let's be honest, we don't really want that. (FxCop, debugger issues, uglyness)
So why won't this code compile - and how can we hack it in such a way that it will?
If we look at the code, what we really would like to do is forward the call. However, according to the MS Partition II, IL exception handler blocks won't work like this, which in this case makes sense because that would imply that the 'exception' object can have different types.
Or to write it in code, we ask the compiler to do something like this (well it's not entirely correct, but it's the closest possible thing I guess):
// Won't compile... damn
try
{
throw new ArgumentOutOfRangeException();
}
catch (ArgumentOutOfRangeException e) {
goto theOtherHandler;
}
catch (IndexOutOfRangeException e) {
theOtherHandler:
Console.WriteLine("Handle!");
}
The reason that this won't compile is quite obvious: what type and value would the '$exception' object have (which are here stored in the variables 'e')? The way we want the compiler to handle this is to note that the common base type of both exceptions is 'Exception', use that for a variable to contain both exceptions, and then handle only the two exceptions that are caught. The way this is implemented in IL is as 'filter', which is available in VB.Net.
To make it work in C#, we need a temporary variable with the correct 'Exception' base type. To control the flow of the code, we can add some branches. Here goes:
Exception ex;
try
{
throw new ArgumentException(); // for demo purposes; won't be caught.
goto noCatch;
}
catch (ArgumentOutOfRangeException e) {
ex = e;
}
catch (IndexOutOfRangeException e) {
ex = e;
}
Console.WriteLine("Handle the exception 'ex' here :-)");
// throw ex ?
noCatch:
Console.WriteLine("We're done with the exception handling.");
The obvious disadvantages for this are that we cannot re-throw properly, and -well let's be honest- that it's quite the ugly solution. The uglyness can be fixed a bit by performing branch elimination, which makes the solution slightly better:
Exception ex = null;
try
{
throw new ArgumentException();
}
catch (ArgumentOutOfRangeException e)
{
ex = e;
}
catch (IndexOutOfRangeException e)
{
ex = e;
}
if (ex != null)
{
Console.WriteLine("Handle the exception here :-)");
}
That leaves just the 're-throw'. For this to work, we need to be able to perform the handling inside the 'catch' block - and the only way to make this work is by an catching 'Exception' object.
At this point, we can add a separate function that handles the different types of Exceptions using overload resolution, or to handle the Exception. Both have disadvantages. To start, here's the way to do it with a helper function:
private static bool Handle(Exception e)
{
Console.WriteLine("Handle the exception here :-)");
return true; // false will re-throw;
}
public static void Main()
{
try
{
throw new OutOfMemoryException();
}
catch (ArgumentException e)
{
if (!Handle(e)) { throw; }
}
catch (IndexOutOfRangeException e)
{
if (!Handle(e)) { throw; }
}
Console.WriteLine("We're done with the exception handling.");
And the other solution is to catch the Exception object and handle it accordingly. The most literal translation for this, based on the context above is this:
try
{
throw new ArgumentException();
}
catch (Exception e)
{
Exception ex = (Exception)(e as ArgumentException) ?? (e as IndexOutOfRangeException);
if (ex != null)
{
Console.WriteLine("Handle the exception here :-)");
// throw ?
}
else
{
throw;
}
}
So to conclude:
If we don't want to re-throw, we might consider catching the right exceptions, and storing them in a temporary.
If the handler is simple, and we want to re-use code, the best solution is probably to introduce a helper function.
If we want to re-throw, we have no choice but to put the code in a 'Exception' catch handler, which will break FxCop and your debugger's uncaught exceptions.
This is a classic problem every C# developer faces eventually.
Let me break your question into 2 questions. The first,
Can I catch multiple exceptions at once?
In short, no.
Which leads to the next question,
How do I avoid writing duplicate code given that I can't catch multiple exception types in the same catch() block?
Given your specific sample, where the fall-back value is cheap to construct, I like to follow these steps:
Initialize WebId to the fall-back value.
Construct a new Guid in a temporary variable.
Set WebId to the fully constructed temporary variable. Make this the final statement of the try{} block.
So the code looks like:
try
{
WebId = Guid.Empty;
Guid newGuid = new Guid(queryString["web"]);
// More initialization code goes here like
// newGuid.x = y;
WebId = newGuid;
}
catch (FormatException) {}
catch (OverflowException) {}
If any exception is thrown, then WebId is never set to the half-constructed value, and remains Guid.Empty.
If constructing the fall-back value is expensive, and resetting a value is much cheaper, then I would move the reset code into its own function:
try
{
WebId = new Guid(queryString["web"]);
// More initialization code goes here.
}
catch (FormatException) {
Reset(WebId);
}
catch (OverflowException) {
Reset(WebId);
}
So you´re repeating lots of code within every exception-switch? Sounds like extracting a method would be god idea, doesn´t it?
So your code comes down to this:
MyClass instance;
try { instance = ... }
catch(Exception1 e) { Reset(instance); }
catch(Exception2 e) { Reset(instance); }
catch(Exception) { throw; }
void Reset(MyClass instance) { /* reset the state of the instance */ }
I wonder why no-one noticed that code-duplication.
From C#6 you furthermore have the exception-filters as already mentioned by others. So you can modify the code above to this:
try { ... }
catch(Exception e) when(e is Exception1 || e is Exception2)
{
Reset(instance);
}
Wanted to added my short answer to this already long thread. Something that hasn't been mentioned is the order of precedence of the catch statements, more specifically you need to be aware of the scope of each type of exception you are trying to catch.
For example if you use a "catch-all" exception as Exception it will preceed all other catch statements and you will obviously get compiler errors however if you reverse the order you can chain up your catch statements (bit of an anti-pattern I think) you can put the catch-all Exception type at the bottom and this will be capture any exceptions that didn't cater for higher up in your try..catch block:
try
{
// do some work here
}
catch (WebException ex)
{
// catch a web excpetion
}
catch (ArgumentException ex)
{
// do some stuff
}
catch (Exception ex)
{
// you should really surface your errors but this is for example only
throw new Exception("An error occurred: " + ex.Message);
}
I highly recommend folks review this MSDN document:
Exception Hierarchy
Maybe try to keep your code simple such as putting the common code in a method, as you would do in any other part of the code that is not inside a catch clause?
E.g.:
try
{
// ...
}
catch (FormatException)
{
DoSomething();
}
catch (OverflowException)
{
DoSomething();
}
// ...
private void DoSomething()
{
// ...
}
Just how I would do it, trying to find the simple is beautiful pattern
It is worth mentioning here. You can respond to the multiple combinations (Exception error and exception.message).
I ran into a use case scenario when trying to cast control object in a datagrid, with either content as TextBox, TextBlock or CheckBox. In this case the returned Exception was the same, but the message varied.
try
{
//do something
}
catch (Exception ex) when (ex.Message.Equals("the_error_message1_here"))
{
//do whatever you like
}
catch (Exception ex) when (ex.Message.Equals("the_error_message2_here"))
{
//do whatever you like
}
I want to suggest shortest answer (one more functional style):
Catch<FormatException, OverflowException>(() =>
{
WebId = new Guid(queryString["web"]);
},
exception =>
{
WebId = Guid.Empty;
});
For this you need to create several "Catch" method overloads, similar to System.Action:
[DebuggerNonUserCode]
public static void Catch<TException1, TException2>(Action tryBlock,
Action<Exception> catchBlock)
{
CatchMany(tryBlock, catchBlock, typeof(TException1), typeof(TException2));
}
[DebuggerNonUserCode]
public static void Catch<TException1, TException2, TException3>(Action tryBlock,
Action<Exception> catchBlock)
{
CatchMany(tryBlock, catchBlock, typeof(TException1), typeof(TException2), typeof(TException3));
}
and so on as many as you wish. But you need to do it once and you can use it in all your projects (or, if you created a nuget package we could use it too).
And CatchMany implementation:
[DebuggerNonUserCode]
public static void CatchMany(Action tryBlock, Action<Exception> catchBlock,
params Type[] exceptionTypes)
{
try
{
tryBlock();
}
catch (Exception exception)
{
if (exceptionTypes.Contains(exception.GetType())) catchBlock(exception);
else throw;
}
}
p.s. I haven't put null checks for code simplicity, consider to add parameter validations.
p.s.2
If you want to return a value from the catch, it's necessary to do same Catch methods, but with returns and Func instead of Action in parameters.
try
{
WebId = new Guid(queryString["web"]);
}
catch (Exception ex)
{
string ExpTyp = ex.GetType().Name;
if (ExpTyp == "FormatException")
{
WebId = Guid.Empty;
}
else if (ExpTyp == "OverflowException")
{
WebId = Guid.Empty;
}
}
In c# 6.0,Exception Filters is improvements for exception handling
try
{
DoSomeHttpRequest();
}
catch (System.Web.HttpException e)
{
switch (e.GetHttpCode())
{
case 400:
WriteLine("Bad Request");
case 500:
WriteLine("Internal Server Error");
default:
WriteLine("Generic Error");
}
}

Categories

Resources