Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 880
Sinan ILYAS Avatar asked Jul 20 '15 11:07

Sinan ILYAS


People also ask

How do you catch unique constraint exception?

To handle unique constraint violations: Catch uniqueness exceptions thrown by the database at the lowest level possible — in the UnitOfWork class. Convert them into Result. Use the UnitOfWork in the controller to explicitly commit pending changes and see if there are any uniqueness constraint violations.

Can we catch SQL exception?

Syntax error in the SQL statement may result in SQL Exception. When such an exception occurs, an object of the SQLException class will be passed to the catch block. By using the information in the SQLException object, we can catch that exception and continue the program.

What is SQL exception in C#?

The exception that is thrown when SQL Server returns a warning or error. This class cannot be inherited.


1 Answers

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.

like image 140
ken2k Avatar answered Sep 21 '22 11:09

ken2k