How to manage the scope of db context in .NET Core when SaveChanges() fails

.net-core asp.net-core c# entity-framework-core

Question

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
}
1
0
9/24/2019 1:10:01 AM

Popular Answer

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

0
9/24/2019 5:44:24 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow