Miguel Moura
Miguel Moura

Reputation: 39474

Injecting DbContext in ASP.NET Core - concrete type or interface?

On an ASP.NET Core project I am injecting Entity Framework DbContext:

public MessageRepository(MyDbContext context)
{
}

And the configuration is:

services
  .AddEntityFramework()
  .AddSqlServer()
  .AddDbContext<MyDbContext>(x => x.UseSqlServer(connectionString);

Should I create an interface IMyDbContext

public class MyDbContext : DbContext, IMyDbContext
{
}

and inject it instead?

public MessageRepository(IMyDbContext context)
{
}

In all ASP.NET Core examples I see the concrete type, DbContext, is being injected and not an interface.

What option should I choose?

Upvotes: 16

Views: 20492

Answers (3)

Uli
Uli

Reputation: 1675

We're always injecting an interface, since it's easier to mock in unit and integration tests.

  1. Are you willing to change the signature of the MessageRepository constructor? It relies on the concrete type.
  2. Do you write tests for your code? Using and interface would make it easier to mock the database context.

If you've answered "no" to one or more of the above, inject the concrete type; otherwise, inject the interface.

[EDIT] use the following.

context services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());

Upvotes: 11

Zinov
Zinov

Reputation: 4119

In my opinion, you should always rely on an interface as @Uli said, but when it comes to the DbContext you need to take in mind that you are exposing all methods of the DbContext of EntityFramework Core

public class MyDbContext : DbContext, IMyDbContext { }

in that case, you don't need to implement any method that you are exposing because DbContext handles that for you.

BUT if EF code change the DbContext and you make an update to your project then you will be on a painful situation of updating your IMyDbContext every time, also all your unit testing. In my opinion, that will give you a lot of headaches.

This answers/questions can help you to understand why https://stackoverflow.com/a/6768712/819153

Unit testing EF - how to extract EF code out from BL?

Upvotes: 1

Claus Nielsen
Claus Nielsen

Reputation: 551

Currently working on a project myself, where I decided to go with 2 interfaces like this

public interface IDbContext : IDisposable
{
    DbContext Instance { get; }
}

and

public interface IApplicationDbContext : IDbContext
{
    DbSet<MyEntity> MyEntities { get; set; }
    ...
}

My concrete DbContext would then just implement the application context interface

public class ApplicationDbContext : DbContext, IApplicationDbContext
{
    public DbContext Instance => this

    public DbSet<MyEntity> MyEntities { get; set; }
}

This allows my implementation of the Application context to be injected as the application context interface, while also providing me access to the DbContext methods through the Instance property getter without having to add methods needed from the DbContext class to the interface.

Until now, this works great.

Upvotes: 13

Related Questions