Entity Framework Core DbContext and Dependency Injection

Pouyan picture Pouyan · Jul 6, 2016 · Viewed 14.3k times · Source

I'm building a service application using Web API, .Net Core and EntityFramework Core.

For configuring options in my DbContext I'm using these lines in "ConfigureServices" method in Startup.cs

 var connection = @"Server=ISSQLDEV;Database=EventManagement;Trusted_Connection=True;";
 services.AddDbContext<EMContext>(options => options.UseSqlServer(connection));

I know that if I add the context as a constructor parameter in the controller .Net will inject the context in the constructor.

But this is not the behavior I want. I don't want my web api to know anything about the dbcontext. I have a DataAccess Project with a repository class that handles all CRUD operations.

This means that I just want to say Repository.AddEvent(evt) in my controller and then repository knows how to handle that.

On the other hand, repository uses a simple dependency resolver to get the right "IDataAdapter" implementation. One of those implementations is SQLDataAdapter. This is the point I need my context.

How can I pass my context all the way to this point?

Answer

natemcmaster picture natemcmaster · Jul 8, 2016

You can solve this by adding your dbcontext via constructor injection to your classes from your data access layer.

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(o => o.UseSqlServer(myConnStr));
        services.AddScoped<Repository>(); // 'scoped' in ASP.NET means "per HTTP request"
    }
}

public class MvcController
{
    private Repository repo;
    public MvcController(Repository repo)
    {
        this.repo = repo;
    }

    [HttpPost]
    public void SomeEndpoint()
    {
        this.repo.AddFoo(new Foo());
    }
}

public class Repository
{
    private DbContext db;
    public Repository(ApplicationDbContext db)
    {
        this.db = db;
    }

    public void AddFoo(Foo obj)
    {
        this.db.Set<Foo>().Add(obj);
        this.db.SaveChanges();
    }
}

If you want to further customize how your DbContext is injected into your DI container, I suggest you look at what .AddDbContext is actually doing. See https://github.com/aspnet/EntityFramework/blob/1.0.0/src/Microsoft.EntityFrameworkCore/EntityFrameworkServiceCollectionExtensions.cs#L142-L158