We have a .NET Core console app that is triggered by an Azure service bus queue. My understanding is that the default lifetime of the DbContext via DI is Scoped
and that it's recommended to let DI and the framework manage the lifetime instead of using using
statements. However, we have the following case where we call SaveChanges()
, it fails, so we try to call it again to write a log to the db. What's the recommended approach here? It feels weird to use using
when the context is injected by DI to the calling class.
try
{
db.Add(new MyEntity());
db.SaveChanges();
}
catch (Exception ex) // a constraint is violated
{
db.Add(new LogEntity("Unable to save MyEntity"));
db.SaveChanges(); // this fails because MyEntity is still in scope of the context
}
My understanding is that the default lifetime of the DbContext via DI is Scoped and that it's recommended to let DI and the framework manage the lifetime instead of using
using
statements.
This is not accurate, DI is a method for instantiating objects, but you can still control the scope of the objects... example using Ninject (more info):
// this would create a new MyType instance on every request
kernel.Bind<IMyType>().To<MyType>().InTransientScope();
// this would share MyType instance within the same Thread
kernel.Bind<IMyType>().To<MyType>().InThreadScope();
// this would share MyType instance within the same Web Request
kernel.Bind<IMyType>().To<MyType>().InRequestScope();
Regarding the scope of DbContext, see Microsoft's recommendation:
A DataContext is lightweight and is not expensive to create. A typical LINQ to SQL application creates DataContext instances at method scope or as a member of short-lived classes that represent a logical set of related database operations.
So it is generally a good idea to share the same instance of DbContext
within the same method... the exception here is with logging. It is not a good idea to mix your Logger's DbContext
with the operations that it is logging. Logging should be independent of these operations... you many choose to log your message in a text file, email, DB... if you want to use DB for logging, you can consider using a different DB for your log message. Also Consider using logging frameworks such as Serilog, NLog, etc