EF 核心无法使用 UseSqlServer 和 SpecFlow

时间:2021-06-02 02:59:52

标签: c# specflow .net-5

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

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

  • API(项目)
    • appsettings.json(不是应该用于规范流测试的那个)
  • 业务(项目)
    • BusinessRegister.cs
  • 数据(项目)
    • MyContext.cs
    • DataRegister.cs
  • BddTest(项目)
    • appsettings.json(具有用于 mycontext 的 bdd 测试的连接字符串)
    • DependencyResolver.cs
    • 各种场景

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

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

位于 appsettings.json 项目中的 BddTest

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

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

<块引用>

System.InvalidOperationException: '使用了一个命名的连接字符串, 但名称“ConnectionStrings:MyContext”未在 应用程序的配置。请注意,命名连接字符串是 仅在使用“IConfiguration”和服务提供者时才受支持, 例如在典型的 ASP.NET Core 应用程序中。

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

3 个答案:

答案 0 :(得分:1)

为了解决这个问题,我做了一些与@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);
    }
}

答案 1 :(得分:0)

使用:

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

其中 _config 是注入到构造函数中的 DI IConfiguration,其中 OnConfiguring 是。

答案 2 :(得分:0)

试试这个:

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