【问题标题】:How to read connection string inside .NET Standard Class library project from ASP.NET Core如何从 ASP.NET Core 读取 .NET 标准类库项目中的连接字符串
【发布时间】:2018-12-20 14:43:31
【问题描述】:

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

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

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

【问题讨论】:

  • 有人介意告诉我投反对票的原因吗?
  • @Christian 我可以在那个问题中看到它提到在类库项目中阅读它?
  • 据我了解,是指在类库项目中创建appsettings.json文件,然后注册到IConfigurationRoot的场景。在我的情况下,我的类库项目中没有任何 appsettings 文件,我也不需要注册 IConfiguration 已经能够在我的 Web 项目中访问的文件。如果我错了,请纠正我?
  • @Nkosi 关于耦合问题:我不知道哪种方法更真实,在类库中有一个应用程序设置,然后使用 IConfigurationRoot 注册它,或者只是通过 IConfiguration 构造函数依赖项从 Web 项目中读取它注射,正如亚历克斯所回答的那样。 XY 问题问题:是的,我可以说它与 Christian 的回答一起进入了 XY 问题方面,而我相信我的问题很清楚,我问如何在我的类库项目中读取连接字符串的 asp.net Core appsettings 文件.

标签: c# dependency-injection connection-string asp.net-core-2.0 class-library


【解决方案1】:

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

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

在您的数据访问层(类库)中,您可以依赖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 Core Web 项目中,您需要“连接”您的依赖项。 在 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();
    }
}

现在,当您的类库中的代码被执行时,ctor 会收到您在 Web 应用程序中设置的 IConfiguration 实例

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

【讨论】:

  • 为了使用 IConfiguration,我的数据访问层项目中是否需要 Microsoft.Extensions.Configuration 包?
  • @LearningCurve 是的,你会的
  • 如果有人正在寻找相同的解决方案,则更新。 _config.GetValue 不再可用,而是 _config.GetSection。
  • @Alex,我想我用错了你的建议,不知何故。在 Startup.cs 中进行连接后,我期望构造函数被“交给 IConfiguration 的实例”,但这似乎没有发生,因为当构造函数认为它没有得到它需要的东西时,我收到以下错误: “没有给出与'ConnectionManager.ConnectionManager(IConfiguration)'所需的形式参数'config'相对应的参数”我是否必须以某种方式手动传递“config”?
【解决方案2】:

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

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

【讨论】:

  • 我已经在我的问题中提到了这种方法(称为 Andrii Litvinov)。令我好奇的是,为什么你认为这种方法更好,而 Andrii 自己建议依赖注入?
  • @LearningCurve 这是一种依赖注入方法,而 Andrii 的解决方案是通过静态类共享价值。 DI 方法在应用程序的可测试性方面更好
  • 我的意思是通过构造函数进行依赖注入。
  • 我建议不要在应用程序的合成根以外的任何地方使用IOptions&lt;T&gt;,而是让Repository 类直接依赖于ConnectionStringConfig,如here 所述。
  • @AlexRiabov 我正在查看您的示例,这似乎是一条不错的路线,但如何定义使用该位的连接字符串名称尚不清楚。
【解决方案3】:

这很简单...在组合根目录中使用 IOptions,就像在 startup.cs 或单独的类库项目中一样:

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

上面使用 Configuration 类来映射包含连接字符串的 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 中设置我的连接字符串。

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

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

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

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

【讨论】:

  • 此解决方案是否需要使用 Dapper DAL?
猜你喜欢
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 2018-03-29
  • 2013-02-23
相关资源
最近更新 更多