I'm trying to catch all SQLExceptions (connection error, timeout, etc) that EF might throw in a single place. I'm using a unit of work pattern with DI so there's no var using = context
for example. Calls like .Single
or .ToList
are used all around the business logic.
Is there any hook or event of class I could overwrite or inject to do this?
Little bit work to do, but this will help you i think:
Encapsulate you DbContext
withing a fake-context and hide your DbSets
. You build an new context which will be the context for you business-logic. This one doesn't give access to the DbSets
, it shows custom-dbSets to the user. The main work will be to build the fake-context, which needs to have all methods you're using on the real dbSets.
/// <summary>
/// This sould no be used anywhere except in MyDbContext2
/// </summary>
public class MyDbContext : DbContext
{
public DbSet<SomeTableClass> SomeTable { get; set; }
}
/// <summary>
/// This will be your context in the business-logic
/// </summary>
public class MyDbContext2
{
private MyDbContext realDb;
public MyDbContext2(string conStr)
{
realDb = new MyDbContext();
}
public MyDbSet<SomeTableClass> SomeFakeTable { get; set; }
}
/// <summary>
/// Fake-set with logging
/// </summary>
/// <typeparam name="T"></typeparam>
public class MyDbSet<T> where T : class
{
private DbSet<T> dbSet;
public MyDbSet(DbSet<T> realDbSet)
{
this.dbSet = realDbSet;
}
public List<T> ToList()
{
try
{
return dbSet.ToList();
}
catch (Exception e)
{
// Do some logging..
throw;
}
}
public T SingleOrDefault()
{
try
{
return dbSet.SingleOrDefault();
}
catch (Exception e)
{
// Do some logging..
throw;
}
}
}
A good idea would be to rename you DbContext
and introduce a the fake-one with the old name. This way Visual Studio will show you which methods you have to implement.