使用 IConfigurationRoot 将应用程序的连接字符串向下传递到 ASP.NET 5 中的存储库 Class 库
Passing application's connection string down to a Repository Class Library in ASP.NET 5 using the IConfigurationRoot
我有一个 ASP.NET 5 MVC Web 应用程序,在 Startup.cs 我看到 public 属性
IConfigurationRoot Configuration
正在设置为
builder.Build();
在整个 MVC Web 应用程序中,我可以简单地执行
Startup.Configuration["Data:DefaultConnection:ConnectionString"]
从 appsettings.json
文件中获取连接字符串。
如何使用构造函数注入将 ASP.NET 5 MVC appsettings.json
中指定的连接字符串传递到我的存储库 Class 库?
更新:
这是所有其他存储库继承自的基本存储库(如您所见,我现在在这里有一个硬编码的连接字符串):
public class BaseRepo
{
public static string ConnectionString = "Server=MYSERVER;Database=MYDATABASE;Trusted_Connection=True;";
public static SqlConnection GetOpenConnection()
{
var cs = ConnectionString;
var connection = new SqlConnection(cs);
connection.Open();
return connection;
}
}
在我的 asp.net 5 网络应用程序中,我的 appsettings.json 文件中有以下内容,这相当于在 .net 4.5 网络应用程序中向 web.config 添加连接字符串:
"Data": {
"DefaultConnection": {
"ConnectionString": "Server=MYSERVER;Database=MYDATABASE;Trusted_Connection=True;"
}
}
此外,在我的 asp.net 5 Web 应用程序中,我的 Startup.cs 中有以下默认代码,它将站点配置加载到 IConfigurationRoot 类型的 public 属性 中:
public IConfigurationRoot Configuration { get; set; }
// Class Constructor
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment())
{
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
builder.AddUserSecrets();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
现在在我的 asp.net 网络应用程序中,如果我想访问任何应用程序设置,我可以简单地执行以下操作:Startup.Configuration["Data:DefaultConnection:ConnectionString"]
但不幸的是,我不能从我的 class 图书馆做到这一点..
如果有人想尝试解决这个问题,请参考重现步骤:
- 创建一个新的 ASP.NET 5 MVC Web 应用程序。
- 向项目中添加另一个 Class 库(包)类型的项目。
- 想办法将应用程序设置从 ASP.NET 5 MVC 应用程序传递到 Class 库
更新后还是不太明白。这是我的代码:
public class BaseRepo
{
private readonly IConfigurationRoot config;
public BaseRepo(IConfigurationRoot config)
{
this.config = config;
}
}
此 class 声明不起作用,因为 BaseRepo 现在需要构造函数参数。
public class CustomerRepo : BaseRepository, ICustomerRepo
{
public Customer Find(int id)
{
using (var connection = GetOpenConnection())
{
...
}
}
}
如果您的项目 startUp.cs
中的 ConfigureServices
包含
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<YourDbContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
并且您的存储库 cs 文件具有构造函数注入,如下所示
public class MyRepo : IRepo
{
private readonly YourDbContext dbContext;
public MyRepo(YourDbContext ctx)
{
dbContext = ctx;
}
}
YourDbContext
会自动解析
在您的 Startup.cs 文件中添加以下方法
public void ConfigureServices(IServiceCollection services) {
services.AddSingleton(_ => Configuration);
}
然后像这样更新您的 BaseRepo class
public class BaseRepo {
private readonly IConfiguration config;
public BaseRepo(IConfiguration config) {
this.config = config;
}
public SqlConnection GetOpenConnection() {
string cs = config["Data:DefaultConnection:ConnectionString"];
SqlConnection connection = new SqlConnection(cs);
connection.Open();
return connection;
}
}
您需要在 class 库项目中创建一个 class 以访问网站项目中的 appsettings.json 和 return 连接字符串。
{
private static string _connectionString;
public static string GetConnectionString()
{
if (string.IsNullOrEmpty(_connectionString))
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
_connectionString = Configuration.Get<string>("Data:MyDb:ConnectionString");
}
return _connectionString;
}
public static IConfigurationRoot Configuration { get; set; }
}
ASP.NET 提供了自己的配置设置传递方式。
假设您的 appSettings.json:
中有这个
{
"Config": {
"Setting1": 1,
"Setting2": "SO"
}
}
那么你需要一个像这样的class:
public class MyConfiguration
{
public int Setting1 { get; set; }
public string Setting2 { get; set; }
}
这允许您通过添加以下行来使用此配置配置您的服务
services.Configure<MyConfigurationDto>(Configuration.GetSection("Config"));
至ConfigureServices
。
然后您可以通过执行以下操作在构造函数中注入配置:
public class SomeController : Controller
{
private readonly IOptions<MyConfiguration> config;
public ServiceLocatorController(IOptions<MyConfiguration> config)
{
this.config = config;
}
[HttpGet]
public IActionResult Get()
{
return new HttpOkObjectResult(config.Value);
}
}
此示例适用于控制器。但是您可以对应用程序的其他层执行相同的操作。
我的存储库 class 中有一个构造函数,它接受数据库连接字符串作为参数。当我添加我的注入存储库时,这对我有用。在 startup.cs 文件的 ConfigureServies() 中添加:
services.AddScoped<IRepos>(c => new Repos(Configuration["DbConnections:ConnStr1"]));
IRepos.cs
是接口,Repos.cs
是实现它的class。当然,Configuration 只是对构建的 IConfigurationRoot
对象的引用。
已经有一种扩展方法可用于专门从 aspsettings.json 获取连接字符串。
像这样在 appsettings.json 中定义连接字符串:
{
"ConnectionStrings": {
"Local": "Data source=.\SQLExpress;Initial Catalog=.......",
"Test:": "Data source=your-server;......"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
}
}
在 Startup.cs
中的 public void ConfigureServices(IServiceCollection services)
方法中,您可以获得这样的连接字符串:
var connectionString = this.Configuration.GetConnectionString("Local");
GetConnectionString
扩展名来自 Microsoft.Extensions.Configuration
。
- 尽情享受吧:)
更新
一开始我不想细说,因为这里的问题已经被标记为已回答。但我想我可以在这里展示我的 2 美分。
如果您确实需要将整个 IConfigurationRoot
对象注入控制器,@Chrono 展示了正确的方法。
如果您不需要整个对象,您应该只获取连接字符串,将其传递到 ConfigureServices()
调用中的 DbContext,然后将 DbContext
注入控制器。 @Prashant Lakhlani 显示正确。
我只是说,在@Prashant Lakhlani post 中,您可以使用 GetConnectionString
扩展来稍微清理一下代码。
一种略有不同的方法是在您的 Class 库中创建一个静态 class,您可以在该库中调用 Startup.cs
中的 Configure(..)
方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
ConnectionManager.SetConfig(Configuration);
}
在这种情况下,我在 ConfigureServices
:
中添加了作为单例的配置
services.AddSingleton(_ => Configuration);
我的 ConnectionManager
看起来像这样:
public class ConnectionManager
{
private static IConfiguration currentConfig;
public static void SetConfig(IConfiguration configuration)
{
currentConfig = configuration;
}
/// <summary>
/// Get a connection to the database.
/// </summary>
public static SqlConnection GetConnection
{
get
{
string connectionString = currentConfig.GetConnectionString("MyConnection");
// Create a new connection for each query.
SqlConnection connection = new SqlConnection(connectionString);
return connection;
}
}
}
这可能有也可能没有关于对象生命周期等问题,我当然不喜欢 static
classes 但据我所知这是一种可行的方法。您甚至可以从配置文件中提取 ConnectionString
并仅发送 Configuration
而不是传递 Configuration
。
我有一个 ASP.NET 5 MVC Web 应用程序,在 Startup.cs 我看到 public 属性
IConfigurationRoot Configuration
正在设置为
builder.Build();
在整个 MVC Web 应用程序中,我可以简单地执行
Startup.Configuration["Data:DefaultConnection:ConnectionString"]
从 appsettings.json
文件中获取连接字符串。
如何使用构造函数注入将 ASP.NET 5 MVC appsettings.json
中指定的连接字符串传递到我的存储库 Class 库?
更新:
这是所有其他存储库继承自的基本存储库(如您所见,我现在在这里有一个硬编码的连接字符串):
public class BaseRepo
{
public static string ConnectionString = "Server=MYSERVER;Database=MYDATABASE;Trusted_Connection=True;";
public static SqlConnection GetOpenConnection()
{
var cs = ConnectionString;
var connection = new SqlConnection(cs);
connection.Open();
return connection;
}
}
在我的 asp.net 5 网络应用程序中,我的 appsettings.json 文件中有以下内容,这相当于在 .net 4.5 网络应用程序中向 web.config 添加连接字符串:
"Data": {
"DefaultConnection": {
"ConnectionString": "Server=MYSERVER;Database=MYDATABASE;Trusted_Connection=True;"
}
}
此外,在我的 asp.net 5 Web 应用程序中,我的 Startup.cs 中有以下默认代码,它将站点配置加载到 IConfigurationRoot 类型的 public 属性 中:
public IConfigurationRoot Configuration { get; set; }
// Class Constructor
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
if (env.IsDevelopment())
{
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
builder.AddUserSecrets();
}
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
现在在我的 asp.net 网络应用程序中,如果我想访问任何应用程序设置,我可以简单地执行以下操作:Startup.Configuration["Data:DefaultConnection:ConnectionString"]
但不幸的是,我不能从我的 class 图书馆做到这一点..
如果有人想尝试解决这个问题,请参考重现步骤:
- 创建一个新的 ASP.NET 5 MVC Web 应用程序。
- 向项目中添加另一个 Class 库(包)类型的项目。
- 想办法将应用程序设置从 ASP.NET 5 MVC 应用程序传递到 Class 库
更新后还是不太明白。这是我的代码:
public class BaseRepo
{
private readonly IConfigurationRoot config;
public BaseRepo(IConfigurationRoot config)
{
this.config = config;
}
}
此 class 声明不起作用,因为 BaseRepo 现在需要构造函数参数。
public class CustomerRepo : BaseRepository, ICustomerRepo
{
public Customer Find(int id)
{
using (var connection = GetOpenConnection())
{
...
}
}
}
如果您的项目 startUp.cs
中的 ConfigureServices
包含
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<YourDbContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
并且您的存储库 cs 文件具有构造函数注入,如下所示
public class MyRepo : IRepo
{
private readonly YourDbContext dbContext;
public MyRepo(YourDbContext ctx)
{
dbContext = ctx;
}
}
YourDbContext
会自动解析
在您的 Startup.cs 文件中添加以下方法
public void ConfigureServices(IServiceCollection services) {
services.AddSingleton(_ => Configuration);
}
然后像这样更新您的 BaseRepo class
public class BaseRepo {
private readonly IConfiguration config;
public BaseRepo(IConfiguration config) {
this.config = config;
}
public SqlConnection GetOpenConnection() {
string cs = config["Data:DefaultConnection:ConnectionString"];
SqlConnection connection = new SqlConnection(cs);
connection.Open();
return connection;
}
}
您需要在 class 库项目中创建一个 class 以访问网站项目中的 appsettings.json 和 return 连接字符串。
{
private static string _connectionString;
public static string GetConnectionString()
{
if (string.IsNullOrEmpty(_connectionString))
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
_connectionString = Configuration.Get<string>("Data:MyDb:ConnectionString");
}
return _connectionString;
}
public static IConfigurationRoot Configuration { get; set; }
}
ASP.NET 提供了自己的配置设置传递方式。
假设您的 appSettings.json:
中有这个{
"Config": {
"Setting1": 1,
"Setting2": "SO"
}
}
那么你需要一个像这样的class:
public class MyConfiguration
{
public int Setting1 { get; set; }
public string Setting2 { get; set; }
}
这允许您通过添加以下行来使用此配置配置您的服务
services.Configure<MyConfigurationDto>(Configuration.GetSection("Config"));
至ConfigureServices
。
然后您可以通过执行以下操作在构造函数中注入配置:
public class SomeController : Controller
{
private readonly IOptions<MyConfiguration> config;
public ServiceLocatorController(IOptions<MyConfiguration> config)
{
this.config = config;
}
[HttpGet]
public IActionResult Get()
{
return new HttpOkObjectResult(config.Value);
}
}
此示例适用于控制器。但是您可以对应用程序的其他层执行相同的操作。
我的存储库 class 中有一个构造函数,它接受数据库连接字符串作为参数。当我添加我的注入存储库时,这对我有用。在 startup.cs 文件的 ConfigureServies() 中添加:
services.AddScoped<IRepos>(c => new Repos(Configuration["DbConnections:ConnStr1"]));
IRepos.cs
是接口,Repos.cs
是实现它的class。当然,Configuration 只是对构建的 IConfigurationRoot
对象的引用。
已经有一种扩展方法可用于专门从 aspsettings.json 获取连接字符串。
像这样在 appsettings.json 中定义连接字符串:
{ "ConnectionStrings": { "Local": "Data source=.\SQLExpress;Initial Catalog=.......", "Test:": "Data source=your-server;......" }, "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information" } } }
在
Startup.cs
中的public void ConfigureServices(IServiceCollection services)
方法中,您可以获得这样的连接字符串:var connectionString = this.Configuration.GetConnectionString("Local");
GetConnectionString
扩展名来自Microsoft.Extensions.Configuration
。- 尽情享受吧:)
更新
一开始我不想细说,因为这里的问题已经被标记为已回答。但我想我可以在这里展示我的 2 美分。
如果您确实需要将整个 IConfigurationRoot
对象注入控制器,@Chrono 展示了正确的方法。
如果您不需要整个对象,您应该只获取连接字符串,将其传递到 ConfigureServices()
调用中的 DbContext,然后将 DbContext
注入控制器。 @Prashant Lakhlani 显示正确。
我只是说,在@Prashant Lakhlani post 中,您可以使用 GetConnectionString
扩展来稍微清理一下代码。
一种略有不同的方法是在您的 Class 库中创建一个静态 class,您可以在该库中调用 Startup.cs
中的 Configure(..)
方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
ConnectionManager.SetConfig(Configuration);
}
在这种情况下,我在 ConfigureServices
:
services.AddSingleton(_ => Configuration);
我的 ConnectionManager
看起来像这样:
public class ConnectionManager
{
private static IConfiguration currentConfig;
public static void SetConfig(IConfiguration configuration)
{
currentConfig = configuration;
}
/// <summary>
/// Get a connection to the database.
/// </summary>
public static SqlConnection GetConnection
{
get
{
string connectionString = currentConfig.GetConnectionString("MyConnection");
// Create a new connection for each query.
SqlConnection connection = new SqlConnection(connectionString);
return connection;
}
}
}
这可能有也可能没有关于对象生命周期等问题,我当然不喜欢 static
classes 但据我所知这是一种可行的方法。您甚至可以从配置文件中提取 ConnectionString
并仅发送 Configuration
而不是传递 Configuration
。