3

In a test project I have the following layers: Web API <-> Service (with DbContext).

I do not use the repository pattern because DbSet is already a repository.

public class MyService : DbContext
{
    public MyService(DbContextOptions<MyDbContext> options)
        : base(options)
    {
    }
    ...
}

I'm wondering if I should inject the DbContext for each service, or create the DbContext within a using statement per method?

DoSomething()
{
   using (var db = new DbContext())
   {
      ...
   }
}

The advantage of the latter would be that I can run different queries in parallel (I have the case, and at the moment three queries are running sequentially).

Or can I even combine both cases?

Guru Stron
  • 102,774
  • 10
  • 95
  • 132

2 Answers2

3

I would argue that second approach goes a bit against the DI principle. Yes, you can setup in DI and inject the DbContextOptions<MyDbContext> and use them for context construction but arguably better approach would be using IDbContextFactory approach:

services.AddDbContextFactory<ApplicationDbContext>(opts => ...);

And then inject and use it in the service:

private readonly IDbContextFactory<ApplicationDbContext> _contextFactory;

public MyService(IDbContextFactory<ApplicationDbContext> contextFactory)
{
    _contextFactory = contextFactory;
}

public void DoSomething()
{
    using (var context = _contextFactory.CreateDbContext()) // should dispose the context for correct usage
    {
        // ...
    }
}

Notice that the DbContext instances created in this way are not managed by the application's service provider and therefore must be disposed by the application.

Or can I even combine both cases?

The context factory approach allows to resolve both factory and context.

Note that in terms of Web applications there is some debate if it actually useful to query the database in parallel (at least as default approach).

Guru Stron
  • 102,774
  • 10
  • 95
  • 132
-1

Here are the steps on how to create a service with several DbContext in C#:

Create a class called DbContextFactory.

  1. This class will be responsible for creating and returning instances of the different DbContexts.
  2. In the DbContextFactory class, create a dictionary of DbContexts. The key of the dictionary will be the name of the DbContext, and the value will be the instance of the DbContext.
  3. In the DbContextFactory class, create a method called GetDbContext. This method will take the name of the DbContext as a parameter and return the instance of the DbContext.
  4. In the Startup class, register the DbContextFactory class as a service. In your code, where you need to access a DbContext, use the DbContextFactory class to get the instance of the DbContext.

Here is an example of the DbContextFactory class:

public class DbContextFactory
{
    private static Dictionary<string, DbContext> _dbContexts = new Dictionary<string, DbContext>();

    public DbContext GetDbContext(string name)
    {
        if (!_dbContexts.ContainsKey(name))
        {
            _dbContexts[name] = new DbContext(name);
        }

        return _dbContexts[name];
    }
}

Here is an example of how to use the DbContextFactory class:

var dbContext = DbContextFactory.GetDbContext("MyDbContext");
Svyatoslav Danyliv
  • 21,911
  • 3
  • 16
  • 32