如何使用 Entity Framework Core 和简单注入器访问 .NET Core WebApi 的 DBContext 中的 AppSettings.json fie?

How do I access AppSettings.json fie in the DBContext of a .NET Core WebApi using Entity Framework Core and Simple Injector?

我正在使用 Entity Framework 核心和简单注入器 IoC 容器构建一个 ASP.NET 核心 WebApi 服务。 该应用程序通过 Npgsql.EntityFrameworkCore.PostgeSQL.

使用 postgresql 数据库

这是来自我的 StartupServicesInstaller 的代码片段:

public class Startup
{
    public IConfiguration Configuration { get; }
    private IConfigurationRoot configurationRoot;
    private Container container;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;

        // Build configuration info
        configurationRoot = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json", optional: true,
                reloadOnChange: true)
            .Build();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

        // Initialize Container
        container = new SimpleInjector.Container();
        container.Options.ResolveUnregisteredConcreteTypes = false;
        container.ConfigureServices();
        
        services.AddSimpleInjector(container, options =>
        {
            options.AddAspNetCore()
            .AddControllerActivation();
            options.AddLogging();
        });
    }
}

服务安装程序:

public static class ServicesInstaller
{
    public static void ConfigureServices(this Container container)
    {
        container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

        //Assembly.Load will not re-load already loaded Assemblies
        container.Register<IFooContext, FooContext>(Lifestyle.Scoped);
        container.Register<FooContext>(Lifestyle.Scoped);
    }
}

这是我的数据库上下文中的代码片段 class:

public interface IFooContext
{
}
    
public class FooContext : DbContext, IFooContext
{
    public FooContext()
    {
    }
    
    protected override void OnConfiguring(
        DbContextOptionsBuilder optionbuilder)
    {
        optionbuilder.UseNpgsql(
            "Server=.;Port=5432;Database=...;User ID=...;Password=...;");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

目前我正在将我的连接字符串硬连接到 PostGreSQL 数据库。我希望能够从数据库上下文中的 AppSettings.json 文件中检索连接字符串。我相信这样做的正确位置是在 OnConfiguring() 方法中。

对吗?

鉴于此模型,我如何正确访问 DBContext class 中的 AppSettings.json 文件?

在 ASP.NET Core icw Simple Injector 和 Entity Framework 中集成时,您有 2 个选择:

  1. 直接在Simple Injector中注册DbContext。这将使 Simple Injector 管理 DbContext.
  2. 的生命周期
  3. 在框架的配置系统中注册 DbContext(即 IServiceCollection)。在那种情况下,DbContext 仍然可以注入到您使用 Simple Injector 进行的其他注册中,因为 Simple Injector 将“拉入”(a.k.a。cross wire)来自框架配置系统的依赖。

在大多数情况下,您应该更喜欢选项 1,因为让 Simple Injector 管理依赖项还允许 Simple Injector 验证并diagnose 注册。

但是由于Entity Framework和.NET Core配置系统的耦合,选项1可以更容易实现。这反映在 Simple Injector 文档中。它states:

In some cases, however, framework and third-party components are tightly coupled to this new configuration system. Entity Framework’s DbContext pooling feature is an example where this tight coupling was introduced—pooling can practically only be used by configuring it in Microsoft’s IServiceCollection. As application developer, however, you wish to use Simple Injector to compose your application components. But those application components need to be fed with those framework and third-party services from time to time, which means framework components need to be pulled in from the .NET configuration system.

这意味着您可以按照所有有关注册 DbContext 的 Microsoft 文档进行操作。例如,您可以按如下方式注册您的 DbContext

// For the full example, see: https://simpleinjector.org/aspnetcore
public class Startup
{
    private Container container = new SimpleInjector.Container();

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        // ASP.NET default stuff here
        services.AddControllers();

        services.AddLogging();

        services.AddSimpleInjector(container, options =>
        {
            options.AddAspNetCore()
                .AddControllerActivation();

            options.AddLogging();
        });
        
        // Add DbContext to IServiceCollection using AddDbContext.
        services.AddDbContext<FooContext>(
            options => options.UseNpgsql(
                "Server=.;Port=5432;Database=...;User ID=...;Password=...;"));

        InitializeContainer();
    }

    private void InitializeContainer()
    {
        // Register all other classes using SImple Injector here. e.g.:
        container.Register<ITimeProvider, TimeProvider>(Lifestyle.Singleton);
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseSimpleInjector(container);

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
        });

        container.Verify();
    }
}

由于 Simple Injector 具有跨线依赖性的能力,您仍然可以将 FooContext 注入到任何由 Simple Injector 注册并创建的 class 中。

注意:即使您将 FooContext 注册到 IServiceCollection,请确保您在 Simple 中注册了尽可能多的 class注射器。当使用 Simple Injector 作为您选择的 DI 容器时,您的所有应用程序组件都应该注册到 Simple Injector 中。 DbContext 是罕见的例外。但是,框架组件仍应注册到 IServiceCollection.