AutoFac / .NET Core - Register DBcontext

Kyle Barnes picture Kyle Barnes · May 2, 2018 · Viewed 15.5k times · Source

I have a new .NET Core Web API project that has the following projects structure:

API -> Business / Domain -> Infrastructure

The API is very thin with only the API methods. The Business / Domain layer has all my business logic. And finally, my Infrastructure layer has my DB classes using EF Core 2.0.

I know using .NET Core built-in Dependency Injection I can add a reference from the API project to the Infrastructure project, then add the following code in the StartUp.cs file:

services.AddDbContext<MyContext>(options => options.UseSqlServer(connectionString));

However, I would like to maintain a more traditional separation of concerns. So far I have added a module in my Infrastructure layer that attempts to make the registration like so:

builder.Register(c =>
        {
            var config = c.Resolve<IConfiguration>();

            var opt = new DbContextOptionsBuilder<MyContext>();
            opt.UseSqlServer(config.GetSection("ConnectionStrings:MyConnection:ConnectionString").Value);

            return new MyContext(opt.Options);
        }).AsImplementedInterfaces().InstancePerLifetimeScope();

The DBContext, however, is not getting registered. Any class that attempts to access the injected DBContext cannot resolve the parameter.

Is there a way to register the DBContext in a separate project using AuftoFac in a .NET Core Web API Project?

Answer

Alex Herman picture Alex Herman · Sep 3, 2018

I use Autofac to register both HttpContextAccessor and DbContext.

builder
    .RegisterType<HttpContextAccessor>()
    .As<IHttpContextAccessor>()
    .SingleInstance();

builder
    .RegisterType<AppDbContext>()
    .WithParameter("options", DbContextOptionsFactory.Get())
    .InstancePerLifetimeScope();

DbContextOptionsFactory

public class DbContextOptionsFactory
{
    public static DbContextOptions<AppDbContext> Get()
    {
        var configuration = AppConfigurations.Get(
            WebContentDirectoryFinder.CalculateContentRootFolder());

        var builder = new DbContextOptionsBuilder<AppDbContext>();
        DbContextConfigurer.Configure(
            builder, 
            configuration.GetConnectionString(
                AppConsts.ConnectionStringName));

        return builder.Options;
    }
}

DbContextConfigurer

public class DbContextConfigurer
{
    public static void Configure(
        DbContextOptionsBuilder<AppDbContext> builder, 
        string connectionString)
    {
        builder.UseNpgsql(connectionString).UseLazyLoadingProxies();
    }
}