21

I have a basic understanding in DI in ASP.NET MVC, but there is a question that bothers me a lot. Does it make any difference to register Dbcontext as 'scoped' or "transient"? Below is some code of a typical mvc application:

public class EmployeeController : Controller
{
    private EmployeeContext _context;

    public EmployeeController(EmployeeContext context)
    {
        _context = context;
    }

    public ActionResult Index()
    {
        return View(context.Employees.ToList());
    }
    
    ...//other action methods that access context's DbSet
}

Let's say we register EmployeeContext as a transient service. After we run the application, the application is listening any incoming requests. Let's say a http request to default /Home/Index occurs so a new instance of EmployeeController needs to be created. DI will provide an instance of EmployeeContext to the controller's constructor first. _context is available for all other action methods too and there is not any other place need to create a new EmployeeContext service.

So after the request is finished, the _context is disposed too. Isn't it the same effect as a scoped service? We meant to register it as "transient" service and in the end it works like a "scoped" service. It seems if really doesn't matter if we register Dbcontext as "scoped" or "transient".

ouflak
  • 2,458
  • 10
  • 44
  • 49
  • 1
    Possible duplicate of https://stackoverflow.com/questions/38138100/addtransient-addscoped-and-addsingleton-services-differences – Wijitha Aug 26 '19 at 14:40
  • The default is scoped, and you should stick with that. There's no reason to use transient. – Chris Pratt Aug 26 '19 at 14:53

2 Answers2

38

If you don't use any other injected services (which are also using your DBContext) there's no difference between scoped and transient.

But if you use other injected services, with "transient" on the DBContext, every service gets his own instance of it. In order to avoid that you should always use "scoped" on the DBContext.

In your example with the following code, with a "transient" EmployeeContext there will be two instances every request:

public class MyService : IMyService 
{
 public MyService(EmployeeContext context)
 {
  // ...
 }
}

public class EmployeeController : Controller
{
    private EmployeeContext _context;
    private _myService;

    public EmployeeController(EmployeeContext context, IMyService myService)
    {
        _context = context;
        _myService = myService;
    }

    public ActionResult Index()
    {
        return View(context.Employees.ToList());
    }

    ...//other action methods that access context's DbSet
}
kreadyf
  • 470
  • 4
  • 5
1

https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/

From the official document, DBContext is designed to be short living and not thread safe. If the DBContext instances are disposed properly, they won't cause concurrency issue. Normally the underlying concurrency issue should be coming from the SQL TCP connection pool. How many DBContext instances created doesn't really matter for the concurrency issue. But it does create object in heap which means you should limit the creation of DBContext object if you have full control to the code flow and guarantee there won't be any thread safety issue. But the instance should not be shared between request threads per my understanding, as it will cause corruption bcz of thread safety issue.

Back to the original question, normally Scoped should be good - https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/#implicitly-sharing-dbcontext-instances-via-dependency-injection

Haibo Song
  • 11
  • 1