【问题标题】:How do I access AppSettings.json fie in the DBContext of a .NET Core WebApi using Entity Framework Core and Simple Injector?如何使用 Entity Framework Core 和 Simple Injector 在 .NET Core WebApi 的 DBContext 中访问 AppSettings.json 文件?
【发布时间】:2021-03-22 13:04:51
【问题描述】:

我正在使用 Entity Framework Core 和 Simple Injector IoC 容器构建 ASP.NET Core WebApi 服务。 该应用程序通过 Npgsql.EntityFrameworkCore.PostgeSQL 使用 postgresql 数据库。

这是我的 StartupServicesInstaller 中的代码 sn-p:

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

ServicesInstaller:

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

这是来自我的 DB Context 类的代码 sn-p:

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 DB。我希望能够从数据库上下文中的 AppSettings.json 文件中检索连接字符串。我相信正确的做法是在 OnConfiguring() 方法中。

对吗?

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

【问题讨论】:

标签: entity-framework-core asp.net-core-webapi simple-injector


【解决方案1】:

在 ASP.NET Core icw 简单注入器和实体框架中集成时,您有 2 个选项:

  1. 直接在Simple Injector中注册DbContext。这将让 Simple Injector 管理 DbContext 的生命周期。
  2. 在框架的配置系统中注册DbContext(即IServiceCollection)。在这种情况下,DbContext 仍然可以注入到您使用 Simple Injector 进行的其他注册中,因为 Simple Injector 将从框架的配置系统中“拉入”(又名交叉线)该依赖项。李>

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

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

但是,在某些情况下,框架和第三方组件与这个新的配置系统紧密耦合。 Entity Framework 的DbContext 池化功能就是引入这种紧密耦合的一个例子——池化实际上只能通过在 Microsoft 的IServiceCollection 中进行配置来使用。然而,作为应用程序开发人员,您希望使用 Simple Injector 来组合您的应用程序组件。但是这些应用程序组件需要不时地被那些框架和第三方服务提供,这意味着框架组件需要从 .NET 配置系统中拉入。

这意味着您可以遵循所有有关注册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 创建的类中。

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

【讨论】:

  • 那么通过在 ConfigureServices() 中的工作,我不再需要在 FooContext 中重写 OnConfiguring() 了吗?
  • 这里我还是有点困惑。在我的示例中,我在 SimpleInjector.Container 对象上注册服务。在您提供的示例中,您正在使用 ServiceCollection(我假设不使用 SimpleInjector)。我刚开始使用 SimpleInjector 并试图弄清楚。
  • @JohnB:在我的回答中,只有DbContextServiceCollection 中注册。我重写了我的答案;希望它能让事情更清楚。另请阅读 Simple Injector 文档的参考集成页面。
猜你喜欢
  • 2019-08-08
  • 2023-03-12
  • 2022-11-21
  • 1970-01-01
  • 2019-02-15
  • 1970-01-01
  • 1970-01-01
  • 2017-09-21
  • 1970-01-01
相关资源
最近更新 更多