EF 核心无法使用带有 SpecFlow 的 UseSqlServer 解析环境变量

EF core unable to resolve environment variable using UseSqlServer with SpecFlow

我正在将 BDD 测试项目转换为使用 EF 核心 5.x 和 SpecFlow 3.x + Specflow.Autofac。执行场景时,上下文无法从环境变量中找到连接字符串。

解决方案设置具有以下结构

场景依赖在所有场景执行前注册;

public static class DependencyResolver
{
    private static IConfiguration config;

    [ScenarioDependencies]
    public static ContainerBuilder CreateContainerBuilder()
    {
        var containerBuilder = new ContainerBuilder();
        if (config == null)
        {
            string fullPath = System.Reflection.Assembly.GetAssembly(typeof(DependencyResolver)).Location;
            string theDirectory = Path.GetDirectoryName(fullPath);

            config = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .SetBasePath(theDirectory)
                .AddEnvironmentVariables()
                .Build();
        }

        containerBuilder.RegisterInstance(config);
        containerBuilder.RegisterTypes(typeof(DependencyResolver).Assembly.GetTypes().Where(t => Attribute.IsDefined(t, typeof(BindingAttribute))).ToArray()).SingleInstance(); 
        containerBuilder.RegisterModule(new DependencyRegister());
        containerBuilder.RegisterModule(new BusinessRegister());
        containerBuilder.RegisterModule(new DataRegister());
        return containerBuilder;
    }
}

DataRegister 寄存器 MyContext;

public class DataRegister : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<MyContext>().AsSelf().InstancePerDependency();
    }
}

MyContext 内部调用 UseSqlServer 尝试解析环境变量

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.EnableDetailedErrors();

    if (!optionsBuilder.IsConfigured)
    {
           optionsBuilder.UseSqlServer("Name=ConnectionStrings:MyContext");
    }
}

位于BddTest项目中的appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.EntityFrameworkCore": "Debug",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "ConnectionStrings": {
    "MyContext": "--"
  }
}

当我尝试 运行 一个场景时,应用程序在尝试在 MyContext 中创建数据库连接时出错;

System.InvalidOperationException: 'A named connection string was used, but the name 'ConnectionStrings:MyContext' was not found in the application's configuration. Note that named connection strings are only supported when using 'IConfiguration' and a service provider, such as in a typical ASP.NET Core application.

如何注册我的 appsettings.json 以便它在 Data 项目中可用并且在使用 optionsBuilder.UseSqlServer("Name=ConnectionStrings:MyContext"); 时可以解决?

使用:

_config.GetValue<string>("ConnectionStrings:MyContext")

其中 _config 是在 OnConfiguring 所在的构造函数中注入的 DI IConfiguration。

试试这个:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.EnableDetailedErrors();

    if (!optionsBuilder.IsConfigured)
    {
       var config = ConfigurationManager.ConnectionStrings["MyContext"];
       var conn = new SqlConnection(config.ConnectionString);

       options.UseSqlServer(conn);
    }
}

为了解决这个问题,我做了一些与@Matheus Dasuke 所建议的非常相似的事情。注入 IConfiguration 然后读出值。这意味着我可以从环境变量、用户机密等中获取属性值。

private static IConfiguration _configuration;

public MyContext(IConfiguration configuration) {
    _configuration = configuration;
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
    optionsBuilder.EnableDetailedErrors();

    if (!optionsBuilder.IsConfigured) {
        var builder = new NpgsqlConnectionStringBuilder("Host=" +
            _configuration.GetConnectionString("Host")) {
            Password = _configuration["Password"],
                Username = _configuration["Username"],
                Database = _configuration["Database"],
        };
        optionsBuilder.UseNpgsql(builder.ConnectionString);
    }
}