如何从 ASP.NET Core 中读取 .NET Standard Class 库项目中的连接字符串

How to read connection string inside .NET Standard Class library project from ASP.NET Core

在我的解决方案中,我有一个 ASP.NET 核心 Web 项目和一个 .NET Standard class 库项目。 Class 库项目是数据访问层,我想从我的数据访问层中的 appsettings.json(ASP.NET 核心项目)读取连接字符串。

我找到了很少的答案,比如 Andrii Litvinov 看起来很容易实现,但他也提到了通过依赖注入实现。我不想选择简单的快捷方式而是寻找依赖注入实现?

我不确定在我的 class 库中包含 appsettings.json 然后通过 IConfigurationRoot 注册它是否是更好的选择(如 JRB 所解释的 ),但在我的场景中,连接字符串在 Web 项目的 appsettings.json 文件中,我不想在我的 class 库项目中使用构造函数依赖注入实现来使用连接字符串。

我建议使用选项模式。您可以使用配置数据创建 class,例如:

public class ConnectionStringConfig
{
    public string ConnectionString { get; set; }
}

启动时注册:

public void ConfigureServices(IServiceCollection services)
{
   ...    
   services.Configure<ConnectionStringConfig>(Configuration);
}

并注入您的数据访问层

private readonly ConnectionStringConfig config;

public Repository(IOptions<ConnectionStringConfig> config) 
{
    this.config = config.Value;
}

您可以注入实现 IConfiguration 的 class 实例 See Here
让我们假设在您的 .net 核心应用程序中,您有一个如下所示的配置文件:

{
  "App": {
    "Connection": {
      "Value": "connectionstring"
    }
  }
}

在您的数据访问层(class 库)中,您可以依赖 IConfiguration

public class DataAccess : IDataAccess
{
    private IConfiguration _config;

    public DataAccess(IConfiguration config)
    {
        _config = config;
    }

    public void Method()
    {
        var connectionString = _config.GetValue<string>("App:Connection:Value"); //notice the structure of this string
        //do whatever with connection string
    }
}

现在,在您的 ASP.net 核心 Web 项目中,您需要 'wire up' 您的依赖项。 在 Startup.cs 中,我正在使用这个(来自默认样板模板)

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

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.AddSingleton<IConfiguration>(Configuration); //add Configuration to our services collection
        services.AddTransient<IDataAccess, DataAccess>(); // register our IDataAccess class (from class library)
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
    }
}

现在,当您的 class 库中的代码被执行时,ctor 将获得您在网络应用程序中设置的 IConfiguration 的实例

注意: 如果您愿意,可以创建强类型设置 class,see here for more information

这很简单...像在 startup.cs 中或在单独的 class 库项目中那样在组合根中使用 IOptions:

  services.AddScoped<IDbConnection, OracleConnection>();
        services.AddScoped<IDbConnection, SqlConnection>();
        services.Configure<DatabaseConnections>(configuration.GetSection("DatabaseConnections"));
        services.AddScoped(resolver =>
        {
            var databaseConnections = resolver.GetService<IOptions<DatabaseConnections>>().Value;
            var iDbConnections = resolver.GetServices<IDbConnection>();
            databaseConnections.OracleConnections.ToList().ForEach(ora =>
            {
                ora.dbConnection = iDbConnections.Where(w => w.GetType() == typeof(OracleConnection)).FirstOrDefault();
                ora.dbConnection.ConnectionString = ora.ConnectionString;
                //ora.Guid = Guid.NewGuid();
            });
            databaseConnections.MSSqlConnections.ToList().ForEach(sql =>
            {
                sql.dbConnection = iDbConnections.Where(w => w.GetType() == typeof(SqlConnection)).FirstOrDefault();
                sql.dbConnection.ConnectionString = sql.ConnectionString;
                //sql.Guid = Guid.NewGuid();
            });
            return databaseConnections;
        });

以上使用配置 class 映射包含连接字符串的 appsettings.json 部分。这是 appsettings.json 文件的示例:

      "DatabaseConnections": {
"OracleConnections": [
  {
    "Alias": "TestConnection1",        
    "ConnectionString": "Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = ) (PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ) ) );User Id=;Password=;"
  },
  {
    "Alias": "TestConnection2",        
    "ConnectionString": "Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = ) (PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ) ) );User Id=;Password=;"
  }
],
"MSSqlConnections": [
  {
    "Alias": "Music",
    "ConnectionString": "Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\MusicLibrary.mdf;Integrated Security=True;Connect Timeout=30"
  }
]
}

IOptions 现在让我能够在运行时在 startup.cs 接近合成根的位置设置我的连接字符串。

这是我用来映射连接字符串的class:

        public class DatabaseConnections : IDatabaseConnections
        {
            public IEnumerable<Connection> OracleConnections { get; set; }
            public IEnumerable<Connection> MSSqlConnections { get; set; }
        }

现在任何服务层都可以访问多个数据库连接和每个请求的提供者!

Github 项目:https://github.com/B-Richie/Dapper_DAL