Reputation: 39474
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
Reputation: 1675
We're always injecting an interface, since it's easier to mock in unit and integration tests.
MessageRepository
constructor? It relies on the concrete type.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
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
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