AutoFac / .NET Core-зарегистрировать DBcontext

у меня есть новый проект .NET Core Web API, который имеет следующую структуру проектов:

API - > бизнес / домен - > инфраструктура

API очень тонкий только с методами API. Уровень Business / Domain имеет всю мою бизнес-логику. И, наконец, мой уровень инфраструктуры имеет мои классы БД, использующие EF Core 2.0.

Я знаю, используя встроенную инъекцию зависимостей .NET Core, я могу добавить ссылку из проекта API в проект инфраструктуры, а затем добавьте следующий код при запуске.cs файл:

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

однако я хотел бы сохранить более традиционное разделение проблем. До сих пор я добавил модуль в свой уровень инфраструктуры, который пытается сделать регистрацию так:

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();

DBContext, однако, не регистрируется. Любой класс, который пытается получить доступ к введенному DBContext, не может разрешить параметр.

есть ли способ зарегистрировать DBContext в отдельный проект с использованием AuftoFac в проекте .NET Core Web API?

3 ответов


Я думаю, что проблема в том, что вы пытаетесь зарегистрироваться MyContext() используя AsImplementedInterfaces(). Обычно DbContext регистрируется не так. Вы должны зарегистрировать и разрешить сам класс.


Я использую Autofac для регистрации обоих HttpContextAccessor и 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();
    }
}

в нужном проекте вы можете создать метод расширения, который добавляет контекст в коллекцию

public static class MyDataExtensions {
    public static IServiceCollection AddMyData(this IServiceCollection services) {
        //...

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

        //...
    }
}

С этим тогда в вашем запуске это просто вопрос вызова расширения, выставленного из другого проекта

services.AddMyData();

//...other settings

проект API является корнем композиции, поэтому он должен знать все соответствующие зависимости в любом случае. По крайней мере, с этим расширением вам не нужно делать прямую ссылку на используемый контекст БД,