如何从 ASP.Net Core 中的 SqlServerDBContextOptionsExtensions 获取连接字符串
How do I get the connection string from the SqlServerDBContextOptionsExtensions in ASP.Net Core
我正在构建一个 ASP.Net 核心 API,但我无法找到从 DBContextOptions 获取连接字符串的方法。
我的 startup.cs 中有 DBContext,如下所示;
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddEntityFrameworkSqlServer()
.AddDbContext<MainContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MainConnection")));
services.AddMvc()
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
}
并且在我的上下文 class 中,我有以下构造函数;
public MainContext(DbContextOptions<MainContext> options) : base(options)
{
}
但它不起作用,除非我在 DBContext class 中添加一个实际的连接字符串,OnConfiguring 方法,如下所示;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//TODO Move connection string to a secure location
optionsBuilder.UseSqlServer(@"Server= .....");
}
当我调试和检查 Configuration.GetConnectionString("MainConnection") 中的值时,我可以看到 Startup.cs 从 appsettings.json 文件中获取正确的连接字符串。
我认为通过 DI 将选项传递到 DbContext class 会传递连接字符串,但 DbContect class 不起作用,除非我有 optionBuilder.UseSqlServer( ) 在 OnConfiguring 方法中。
我发现了这个 SO post ,它讨论了使用以下代码从选项 属性
中提取连接字符串
public ResourceDbContext(DbContextOptions options) : base(options)
{
_connectionString = ((SqlServerOptionsExtension)options.Extensions.First()).ConnectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(_connectionString);
}
但是当我尝试使用它时,我发现 options.Extensions
中不再有 First() 方法
所以,我的第一个问题是...
为什么 DBContext class 无需在 OnConfiguring 方法中添加连接字符串就无法工作
我的第二个问题是...
如果 OnCONfiguring 方法中需要连接字符串,我如何从 DbContextOptions 选项对象中获取它而不是必须在 OnConfiguring 方法中显式提供它 --> optionsBuilder.UseSqlServer(@"Server= .....");
在您的 appsettings.json
中,您将创建以下内容:
{
"Database" : {
"ConnectionString" : "..."
}
}
然后在您的 ConfigureServices
中,您将执行以下操作:
services.AddSingleton(_ => Configuration);
这将基本上填充 IConfigurationRoot
属性。您可以在任何地方注入,并通过以下方式访问连接字符串:
private readonly IConfigurationRoot configuration;
private IDbConnection dbConnection { get; }
public Example(IConfigurationRoot configuration)
{
this.Configuration = configuration;
dbConnection = new SqlConnection(this.configuration.GetConnectionString("..."));
}
我的结构有点奇怪,你真的会简单地将 ConnectionString
传递给另一个 class 或注入方法,但这为你演示。但我相信 Entity Framework7 有一个工厂可以直接接受连接字符串。希望这对你有所帮助。
在Entity Framework里面你的ConfigureServices
应该是这样的:
services.AddSingleton<dbContext>(_ => new dbContext(Configuration.GetConnectionString("...")));
public class dbContext : DbContext
{
public dbContext(string dbConnection) : base(dbConnection)
{
}
}
一些额外的 documentation.
至少对于 EF Core 1.1,您需要使用 FindExtension<SqlServerOptionsExtension>()
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure.Internal;
namespace MyNamespace
{
public class MyContext : DbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
var sqlServerOptionsExtension =
options.FindExtension<SqlServerOptionsExtension>();
if(sqlServerOptionsExtension != null)
{
string connectionString = sqlServerOptionsExtension.ConnectionString;
}
}
}
}
如果您在 Startup.cs
中使用 opt.UseInMemoryDatabase()
,则可以进行空值检查
对于 EntityFrameworkCore 2.1.4
,您的连接字符串在 appsettings.json
中应该是这样的
"ConnectionStrings": {
"Connection1": "....",
"Connection2": "..."
},
在 Startup.cs
中的 ConfigureServices
方法中添加以下行
services.AddSingleton(provider => Configuration);
在这些行之后,
services.AddDbContext<MyContextContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("Connection1")));
services.AddScoped<DbContext, MyContext>();
并且你的数据库上下文class应该修改如下。
public partial class MyContext : DbContext
{
private readonly IConfiguration _configuration;
private IDbConnection DbConnection { get; }
public MyContext(DbContextOptions<MyContext> options, IConfiguration configuration)
: base(options)
{
this._configuration = configuration;
DbConnection = new SqlConnection(this._configuration.GetConnectionString("Connection1"));
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(DbConnection.ToString());
}
}
}
我正在构建一个 ASP.Net 核心 API,但我无法找到从 DBContextOptions 获取连接字符串的方法。
我的 startup.cs 中有 DBContext,如下所示;
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddEntityFrameworkSqlServer()
.AddDbContext<MainContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MainConnection")));
services.AddMvc()
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
}
并且在我的上下文 class 中,我有以下构造函数;
public MainContext(DbContextOptions<MainContext> options) : base(options)
{
}
但它不起作用,除非我在 DBContext class 中添加一个实际的连接字符串,OnConfiguring 方法,如下所示;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
//TODO Move connection string to a secure location
optionsBuilder.UseSqlServer(@"Server= .....");
}
当我调试和检查 Configuration.GetConnectionString("MainConnection") 中的值时,我可以看到 Startup.cs 从 appsettings.json 文件中获取正确的连接字符串。
我认为通过 DI 将选项传递到 DbContext class 会传递连接字符串,但 DbContect class 不起作用,除非我有 optionBuilder.UseSqlServer( ) 在 OnConfiguring 方法中。
我发现了这个 SO post
public ResourceDbContext(DbContextOptions options) : base(options)
{
_connectionString = ((SqlServerOptionsExtension)options.Extensions.First()).ConnectionString;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(_connectionString);
}
但是当我尝试使用它时,我发现 options.Extensions
中不再有 First() 方法所以,我的第一个问题是...
为什么 DBContext class 无需在 OnConfiguring 方法中添加连接字符串就无法工作
我的第二个问题是...
如果 OnCONfiguring 方法中需要连接字符串,我如何从 DbContextOptions 选项对象中获取它而不是必须在 OnConfiguring 方法中显式提供它 --> optionsBuilder.UseSqlServer(@"Server= .....");
在您的 appsettings.json
中,您将创建以下内容:
{
"Database" : {
"ConnectionString" : "..."
}
}
然后在您的 ConfigureServices
中,您将执行以下操作:
services.AddSingleton(_ => Configuration);
这将基本上填充 IConfigurationRoot
属性。您可以在任何地方注入,并通过以下方式访问连接字符串:
private readonly IConfigurationRoot configuration;
private IDbConnection dbConnection { get; }
public Example(IConfigurationRoot configuration)
{
this.Configuration = configuration;
dbConnection = new SqlConnection(this.configuration.GetConnectionString("..."));
}
我的结构有点奇怪,你真的会简单地将 ConnectionString
传递给另一个 class 或注入方法,但这为你演示。但我相信 Entity Framework7 有一个工厂可以直接接受连接字符串。希望这对你有所帮助。
在Entity Framework里面你的ConfigureServices
应该是这样的:
services.AddSingleton<dbContext>(_ => new dbContext(Configuration.GetConnectionString("...")));
public class dbContext : DbContext
{
public dbContext(string dbConnection) : base(dbConnection)
{
}
}
一些额外的 documentation.
至少对于 EF Core 1.1,您需要使用 FindExtension<SqlServerOptionsExtension>()
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure.Internal;
namespace MyNamespace
{
public class MyContext : DbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
var sqlServerOptionsExtension =
options.FindExtension<SqlServerOptionsExtension>();
if(sqlServerOptionsExtension != null)
{
string connectionString = sqlServerOptionsExtension.ConnectionString;
}
}
}
}
如果您在 Startup.cs
opt.UseInMemoryDatabase()
,则可以进行空值检查
对于 EntityFrameworkCore 2.1.4
,您的连接字符串在 appsettings.json
"ConnectionStrings": {
"Connection1": "....",
"Connection2": "..."
},
在 Startup.cs
ConfigureServices
方法中添加以下行
services.AddSingleton(provider => Configuration);
在这些行之后,
services.AddDbContext<MyContextContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("Connection1")));
services.AddScoped<DbContext, MyContext>();
并且你的数据库上下文class应该修改如下。
public partial class MyContext : DbContext
{
private readonly IConfiguration _configuration;
private IDbConnection DbConnection { get; }
public MyContext(DbContextOptions<MyContext> options, IConfiguration configuration)
: base(options)
{
this._configuration = configuration;
DbConnection = new SqlConnection(this._configuration.GetConnectionString("Connection1"));
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(DbConnection.ToString());
}
}
}