web-dev-qa-db-ja.com

AutoFac / .NET Core-DBcontextの登録

次のプロジェクト構造を持つ新しい.NET Core Web APIプロジェクトがあります。

API->ビジネス/ドメイン->インフラストラクチャ

APIは非常に薄く、APIメソッドのみです。ビジネス/ドメインレイヤーには、すべてのビジネスロジックがあります。そして最後に、インフラストラクチャレイヤーにはEF Core 2.0を使用するDBクラスがあります。

.NET Core組み込みの依存性注入を使用していることを知っています。APIプロジェクトからインフラストラクチャプロジェクトに参照を追加し、StartUp.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にアクセスしようとするクラスは、パラメーターを解決できません。

。NET Core Web APIプロジェクトでAuftoFacを使用して、DBContextを別のプロジェクトに登録する方法はありますか?

12
Kyle Barnes

問題は、MyContext()を使用してAsImplementedInterfaces()を登録しようとしていることだと思います。これは、DbContextが通常登録される方法ではありません。クラス自体を登録して解決する必要があります。

6

Autofacを使用して、HttpContextAccessorDbContextの両方を登録します。

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();
    }
}
11
Alex Herman

Autofacバージョン4.8.1の別の簡単なソリューション

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().AddControllersAsServices();

        services.AddDbContext<MyContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ConnectionStrings:MyConnection:ConnectionString")));

        var builder = new ContainerBuilder();

        builder.Populate(services);

        //...
        // Your interface registration
        //...

        builder.Build(Autofac.Builder.ContainerBuildOptions.None);
    }
2
Çağlar Duman

目的のプロジェクトでは、コレクションにコンテキストを追加する拡張メソッドを作成できます

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

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

        //...
    }
}

それから、あなたのスタートアップでは、他のプロジェクトから公開されている拡張機能を呼び出すだけです

services.AddMyData();

//...other settings

APIプロジェクトは構成ルートであるため、とにかくすべての関連する依存関係を知る必要があります。少なくともこの拡張機能を使用すると、使用されているdbコンテキストを直接参照する必要はありません。

1
Nkosi