3

我建立一个ASP.Net核心API,我一直没有能够找到一种方法来从DBContextOptions获取连接字符串。我如何从SqlServerDBContextOptionsExtensions在ASP.Net核心

我在我的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= ....."); 

} 

我可以看到Startup.cs从appsettings.json文件中获取正确的连接字符串时,我调试和检查Configuration.GetConnectionString值(“MainConnection”)。

我认为,经过选择进入的DbContext类通过DI会通过连接字符串,但DbContect类没有工作,除非我有optionBuilder.UseSqlServer()在OnConfiguring方法。

我发现这个SO发布https://stackoverflow.com/questions/33532599/asp-net-5-multiple-dbcontext-problems,大约使用下面的代码会谈提取选项属性

public ResourceDbContext(DbContextOptions options) : base(options) 
{ 
    _connectionString = ((SqlServerOptionsExtension)options.Extensions.First()).ConnectionString; 
} 


protected override void OnConfiguring(DbContextOptionsBuilder options) 
{ 
    options.UseSqlServer(_connectionString); 
} 

连接字符串,但是当我尝试使用它,我发现有不再在options.Extensions

所以,我的第一个问题是首先()方法...

为什么没有的DbContext类的工作,而无需添加连接字符串中的OnConfiguring方法

我的第二个问题是...

如果连接字符串在OnCOnfiguring方法所需要的,我怎么能得到它从DbContextOptions选项对象,而不是明确地提供它在OnConfiguring方法 - > optionsBuilder .UseSqlServer(@“Server = .....”);

回答

2

里面的你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有一个工厂直接接受连接字符串。希望这可以帮助你。

在实体框架应该是你这样的ConfigureServices内:

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

    } 
} 

一些额外的documentation

0

至少为EF核心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()