在ASP.net Core 2 MVC应用程序中,从appSettings.json存储/检索ConnectionString

11

我正在寻找在 .net Core 2 MVC 应用程序中以最佳实践方式存储连接字符串的方法(就像在 MVC 5 中的 web.config 中所做的那样)。

我想使用 Dapper 而不是 EF(我找到了许多 EF 示例)。

类似于这样:

{
  "ConnectionStrings": {
    "myDatabase": "Server=.;Database=myDatabase;Trusted_Connection=true;"
  },

  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}
当然有很多在线示例。但是我找不到适用于.NET Core 2.0的内容。
1和2之间有几个更改,我想确保我使用的是版本2的最佳实践。
我找到了这个示例,但它似乎是.NET Core 1: Visual Studio 2017 - MVC Core - Part 05 - Connection String from appsettings.json 这个示例使用键值对appsettings,而不是连接字符串: Read AppSettings in ASP.NET Core 2.0 同样不清楚这是否是.NET Core 1或2:Net Core Connection String Dapper visual studio 2017

1
只需使用 "ConnectionStrings": {...}ConfigurationExtensions.GetConnectionString - 这没有改变,并遵循明显的约定(当然是基于个人意见)。 - Kirk Larkin
谢谢 - 我不是很明白,请问能否详细解释一下? - niico
自从Core首次推出以来,这方面没有任何变化。但是,在实际应用中,您最有可能使用环境变量或类似Azure Key Vault的东西,而不是appsettings.json,以便您不会将实际凭据提交到源代码中。对于本地开发连接字符串来说,这是可以接受的。 - Chris Pratt
有趣的是,即使连接字符串不包含登录凭据(在我的情况下确实如此),只有数据库名称? - niico
我发现这更为直接 - https://dev59.com/QFYN5IYBdhLWcg3wxqhu#51780754 - Prashanth Palaniswamy
2个回答

16

appsettings.json中定义您的连接字符串

{
    "connectionStrings": {
        "appDbConnection": "..."
    }
}

读取启动时的值

如果您遵循惯例并在connectionStrings下定义连接字符串,您可以使用扩展方法GetConnectionString()来读取其值。

public class Startup
{
    public IConfiguration Configuration { get; private set; }

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

    public void ConfigureServices(IServiceCollection services)
    {
        // Since you said you're using Dapper, I guess you might want to
        // inject IDbConnection?
        services.AddTransient<IDbConnection>((sp) => 
            new SqlConnection(this.Configuration.GetConnectionString("appDbConnection"))
        );

        // ...
    }
}

在存储库中使用IDbConnection?

public interface ISpecificationRepository
{
    Specification GetById(int specificationId);
}

public SpecificationRepository : ISpecificationRepository
{
    private readonly IDbConnection _dbConnection;

    public SpecificationRepository(IDbConnection dbConnection)
    {
        _dbConnection = dbConnection;
    }

    public Specification GetById(int specificationId)
    {
        const string sql = @"SELECT * FROM [YOUR_TABLE]
                             WHERE Id = @specId;";

        return _dbConnection
            .QuerySingleOrDefault<Specification>(sql,
                new { specId = specificationId });
    }
}

只需要在POCO中获取连接字符串?

您可以使用Options 设计模式

  1. 定义一个与 appsettings.json 中的 JSON 对象结构完全匹配的类。

public class ConnectionStringConfig
{
    public string AppDbConnection { get; set; }
}
  • 在启动时注册该配置

  • public void ConfigureServices(IServiceCollection services)
    {
       // ...
    
       services.Configure<ConnectionStringConfig>(
           this.Configuration.GetSection("connectionStrings")
       );
    
       // ...
    }
    
  • 在你的 POCO 中接收访问器

    public class YourPoco
    {
        private readonly ConnectionStringConfig _connectionStringConfig;
    
        public YourPoco(IOptions<ConnectionStringConfig> configAccessor)
        {
            _connectionStringConfig = configAccessor.Value;
    
            // Your connection string value is here:
            // _connectionStringConfig.AppDbConnection;
        }
    }
    
  • 注意事项:

    1. 查看我的示例代码,了解如何在Core 1.x和2.0上从appsettings.json中读取值。
    2. 如果您有多个连接字符串,请参阅我的设置方式

    我需要在数据访问类中读取此值 - 该类当前为 POCO。所有这些 DI(依赖注入)的东西都很棒,但现在我只需要像以前一样在 POCO 中访问连接字符串。我该怎么做? - niico
    好的,谢谢-这就是我想到的,只是你的例子和你的json不一致,所以我不确定。应该把“connectionStringConfig”改成“connectionStrings”吗? - niico
    1
    我无法在评论区进行任何详细的解释。您需要阅读https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.0。 - David Liang
    如果有人拿到了代码,那么数据库访问甚至服务器访问都会受到威胁,你没有保护敏感数据。 - victorvartan
    为了在开发过程中安全地存储应用程序设置数据,请访问https://learn.microsoft.com/en-us/dotnet/standard/microservices-architecture/secure-net-microservices-web-applications/developer-app-secrets-storage - David Liang
    显示剩余16条评论

    3

    只需像下面在appsettings.json中设置即可:

    "ConnectionStrings": {
        "DefaultConnection": "Data Source=;Initial Catalog=;Persist Security Info=True;User ID=; Password=;"
    }
    

    在 Startup.cs 中按照以下方式获取它:
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
    
            builder.AddEnvironmentVariables();
            Configuration = builder.Build();
        }
    
        public IConfigurationRoot Configuration { get; }
    }
    

    使用依赖注入在控制器中注入配置,如下所示:

    public class MyController : Controller
    {
        private readonly IConfiguration _configuration;
        private string connectionString;
    
        public MyController(IConfiguration configuration) 
        {
            _configuration = configuration;
    
            connectionString = _configuration.GetConnectionString("DefaultConnection");
        }
    }
    

    我的Startup构造函数已经有(IConfiguration configuration)。将其更改为(IHostingEnvironment env)会产生什么影响?有什么缺点吗? - niico
    我应该保留另一个构造函数吗? - niico
    你真的需要使用IConfigurationRoot而不是仅仅使用IConfiguration吗?如果是这样,为什么? - niico
    我还需要从Data类访问connectionstring,而不是从控制器访问。我尝试使用与MyController相同的构造函数创建POCO类,但它不起作用(connectionString为null)- 我错过了什么?控制器如何将配置传递给其构造函数? - niico
    1
    控制器使用依赖注入获取它,如果您像上面的代码示例一样使用IConfiguration并在构造函数中初始化它,则不会出现该错误。 - Riddhi
    Configuration是只读的时候,你如何执行**Configuration = builder.Build();**操作? - Bill Roberts

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接