如何從ASP.Net Core中的SqlServerDBContextOptionsExtensions獲取連接字符串

asp.net-core asp.net-core-middleware asp.net-core-mvc c# entity-framework-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();
        });
}

在我的Context類中,我有以下構造函數;

public MainContext(DbContextOptions<MainContext> options) : base(options)
{

}

但除非我在DBContext類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類會傳遞連接字符串,但DbContect類不起作用,除非我在OnConfiguring方法中有optionBuilder.UseSqlServer()。

我發現這個SO帖子https://stackoverflow.com/questions/33532599/asp-net-5-multiple-dbcontext-problems ,它談到使用以下代碼從options屬性中提取連接字符串

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類不工作而不必在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傳遞給另一個類,或者註入方法,但這會為你演示。但我相信Entity Framework 7有一個工廠直接接受連接字符串。希望這會幫助你。

在Entity Framework中,它應該在您的ConfigureServices是這樣的:

services.AddSingleton<dbContext>(_ => new dbContext(Configuration.GetConnectionString("...")));
public class dbContext : DbContext
{
     public dbContext(string dbConnection) : base(dbConnection)
     {

     }
}

一些額外的文檔


熱門答案

至少對於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()opt.UseInMemoryDatabase()空檢查



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因