In an application using Entity Framework 6, I track the changes made on tables in the database in a specially designed entity. They track the changes on all tables, including their own table.
So if an exception occurs while saving changes in the database, I delete all of the pending tracking entities in order to avoid creating new and new trackers recursively, log the exception and exit the saving method.
However, if the exception is caused due to connection timeout, I try 3 times to resave the changes, while changing the EntityState of the tracking entities to avoid creating unnecessary trackers. In order to accomplish that, I need to catch a DbUpdateException, get the SqlException down the hierarchy of exceptions, and check its number. However, I'm not sure how deep is the SqlException in the hierarchy. To accomplish successfully getting the Sql Exception, I wrote this:
catch (DbUpdateException duEx)
{
var inner = new Exception();
inner = duEx;
do
{
inner = inner.InnerException;
}
while (!(inner is SqlException) && inner != null);
var innerEx = inner as SqlException;
if (innerEx != null && innerEx.Number == -2)
{
//do job here
}
I tested it and it seems to work, however it looks a bit clumsy. So my question is: Is there any way of getting the SqlException, if any, directly?
What I was wondering is whether there is already some 3rd party extension method which I could use
No, but you can create it yourself:
public static class Helper
{
public static TException GetInnerException<TException>(this Exception ex) where TException : Exception
{
return ex.InnerException != null
? ex.InnerException as TException ?? GetInnerException<TException>(ex.InnerException)
: null;
}
}
And use it :
catch (DbUpdateException duEx)
{
if (duEx.GetInnerException<SqlException>()?.Number == -2)
{
//do job here
}
}