如何从ASP.Net Core中的SqlServerDBContextOptionsExtensions获取连接字符串

时间:2016-12-15 16:52:22

标签: c# asp.net-core asp.net-core-mvc entity-framework-core asp.net-core-middleware

我正在构建一个ASP.Net Core 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(&#34; MainConnection&#34;)中的值时,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方法中显式提供它 - &gt; optionsBuilder.UseSqlServer(@&#34; Server = .....&#34;);

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

至少对于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;
            }
        }
    }
}

如果您在opt.UseInMemoryDatabase()

中使用Startup.cs,则会进行空检查

答案 2 :(得分:0)

对于EntityFrameworkCore 2.1.4,您的连接字符串应类似于appsettings.json

  "ConnectionStrings": {
    "Connection1": "....",
    "Connection2": "..."
  },

将以下行添加到ConfigureServices中的Startup.cs方法中

 services.AddSingleton(provider => Configuration);

在这些行之后,

 services.AddDbContext<MyContextContext>
            (options => options.UseSqlServer(Configuration.GetConnectionString("Connection1")));
 services.AddScoped<DbContext, MyContext>();

您的数据库上下文类应进行如下修改。

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());
            }
        }
    }