从appsettings.json获取ConnectionString,而不是在.NET Core 2.0 App

时间:2017-08-21 12:09:57

标签: asp.net-core connection-string appsettings

我在NET Core2.0 App中有以下类。

// required when local database does not exist or was deleted
public class ToDoContextFactory : IDesignTimeDbContextFactory<AppContext>
{
    public AppContext CreateDbContext(string[] args)
    {
        var builder = new DbContextOptionsBuilder<AppContext>();
        builder.UseSqlServer("Server=localhost;Database=DbName;Trusted_Connection=True;MultipleActiveResultSets=true");
        return new AppContext(builder.Options);
    }
}

当Core不存在时,Core 2.0中需要进行迁移,并且必须在运行 update-database 时创建。 Unable to create migrations after upgrading to ASP.NET Core 2.0

我希望在2个地方(此处和appsettings.json中)没有ConnectionString,但仅限于.json 所以我试图替换

"Server=localhost;Database=DbName;Trusted_Connection=True;MultipleActiveResultSets=true"

ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString

但它不起作用,我得到空值。

更新1:
请注意,在Core 2中明确添加.json是不必要的,所以问题不在于文件 https://andrewlock.net/exploring-program-and-startup-in-asp-net-core-2-preview1-2/

更新2:
此外,我已经使用Configuration从.json发送ConnectionString到Context:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<AppContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    }
}

但我不能将此用于 ToDoContextFactory ,因为它没有配置,迁移使用 ToDoContextFactory ,因此应用程序根本没有运行。

解: 根据@JRB的回答,我的工作方式如下:

public AppContext CreateDbContext(string[] args)
{
    string projectPath = AppDomain.CurrentDomain.BaseDirectory.Split(new String[] { @"bin\" }, StringSplitOptions.None)[0];
    IConfigurationRoot configuration = new ConfigurationBuilder()
        .SetBasePath(projectPath)
        .AddJsonFile("appsettings.json")
        .Build();
    string connectionString = configuration.GetConnectionString("DefaultConnection");

    var builder = new DbContextOptionsBuilder<AppContext>();
    builder.UseSqlServer(connectionString);

    return new AppContext(builder.Options);
}

10 个答案:

答案 0 :(得分:47)

步骤1:在OnConfiguring()

中包含以下内容
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
            .AddJsonFile("appsettings.json")
            .Build();
        optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
    }

第2步:创建appsettings.json:

  {
    "ConnectionStrings": {       
      "DefaultConnection": "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"        
    } 
  }

第3步:将appsettings.json硬拷贝到正确的目录

  Hard copy appsettings.json.config to the directory specified in the AppDomain.CurrentDomain.BaseDirectory directory. 
  Use your debugger to find out which directory that is.        

假设:您已经在项目中包含了Microsoft.Extensions.Configuration.Json包(从Nuget获取)。

答案 1 :(得分:4)

实际上有一种默认模式可用于实现此结果,而无需实现IDesignTimeDbContextFactory并执行任何配置文件复制。

详见this doc,其中还讨论了框架在设计时尝试实例化DbContext的其他方式。

具体来说,您利用了一个新的钩子,在本例中是一个public static IWebHost BuildWebHost(string[] args)形式的静态方法。文档另有说明,但这种方法可以存在于您的入口点(see src)的任何一个类中。实现这一点是1.x to 2.x migration document中的指导的一部分,并且对代码的看法并不完全明显,对WebHost.CreateDefaultBuilder(args)的调用除其他外,是以新项目开始的默认模式连接您的配置用。这就是让迁移等设计时服务使用配置所需的一切。

以下是有关内心深处正在发生的事情的详细信息:

在添加迁移时,当框架尝试创建您的DbContext时,first会将它找到的任何IDesignTimeDbContextFactory实现添加到可用于创建您的工厂方法的集合中上下文,然后它通过前面讨论的静态钩子获取配置的服务,looks获取使用DbContextOptions注册的任何上下文类型(当您使用Startup.ConfigureServices时,AddDbContext中会出现这种情况或AddDbContextPool)并添加这些工厂。最后,通过程序集looks为任何DbContext派生类创建一个工厂方法,只调用Activator.CreateInstance作为最后的冰雹玛丽。

框架使用的优先顺序与上面相同。因此,如果您实现了IDesignTimeDbContextFactory,它将覆盖上面提到的钩子。但是,对于大多数常见方案,您不需要IDesignTimeDbContextFactory

答案 2 :(得分:4)

在ASPNET Core中,您可以在Startup.cs

中进行操作
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<BloggingContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase")));
}

您在appsettings.json中定义的连接

{
  "ConnectionStrings": {
    "BloggingDatabase": "..."
  },
}

来自MS docs

的示例

答案 3 :(得分:3)

如何将它作为dp注入传递给该类? 在ConfigureServices中:

services.Configure<MyOptions>(Configuration);

创建类来保存json字符串:

public class MyOptions
{
    public MyOptions()
    {

    }
    public string Option1 { get; set; }
    public string Option2 { get; set; }
}    

将字符串添加到json文件:

"option1": "somestring",
"option2": "someothersecretstring"

在需要这些字符串的类中,以构造函数的形式传入:

public class SomeClass
{
 private readonly MyOptions _options;

    public SomeClass(IOptions<MyOptions> options)
    {
        _options = options.Value;           
    }    

 public void UseStrings()
 {
   var option1 = _options.Option1;
    var option2 = _options.Option2;
 //code
 }
}

答案 4 :(得分:2)

以上解决方案和Microsoft文档中都缺少一些内容。如果您按照上述文档中的链接链接到GitHub存储库,则将找到真正的解决方案。

我认为造成混淆的是,许多人使用的默认模板没有 not 包含Startup的默认构造函数,因此人们不一定知道注入的Configuration的来源。

因此,在Startup.cs中,添加:

 public IConfiguration Configuration { get; }
 public Startup(IConfiguration configuration) 
 {
     Configuration = configuration;
 }

,然后在ConfigureServices方法中添加其他人说的话...

services.AddDbContext<ChromeContext>(options =>                    
    options.UseSqlServer(Configuration.GetConnectionString("DatabaseConnection")));

您还必须确保已创建appsettings.json文件,并具有与此类似的连接字符串部分

{
  "ConnectionStrings": {
    "DatabaseConnection": "Server=MyServer;Database=MyDatabase;Persist Security Info=True;User ID=SA;Password=PASSWORD;MultipleActiveResultSets=True;"
  }
}

当然,您必须对其进行编辑以反映您的配置。

谨记的事情。这是在.Net Standard 2.1项目中使用Entity Framework Core 3进行测试的。 我需要为以下项添加nuget软件包: Microsoft.EntityFrameworkCore 3.0.0 Microsoft.EntityFrameworkCore.SqlServer 3.0.0,因为这是我正在使用的,也是访问UseSqlServer所必需的。

答案 5 :(得分:0)

您也可以在ASP.NET Core 2中通过在appSettings.json文件中定义连接字符串来执行此操作。然后在Startup.cs中指定要使用的连接字符串。

appSettings.json

{
    "connectionStrings": {
        "YourDBConnectionString": "Server=(localdb)\\mssqllocaldb;Database=YourDB;Trusted_Connection=True"
    }
}

Startup.cs

public static IConfiguration Configuration { get; private set;}

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}
var connectionString = Configuration["connectionStrings:YourDBConnectionString"];
services.AddDbContext<YourDbContext>(x => x.UseSqlServer(connectionString));

答案 6 :(得分:0)

  1. 将以下代码添加到startup.cs文件中。

    public void ConfigureServices(IServiceCollection services)
    {
        string con = Configuration.GetConnectionString("DBConnection");
        services.AddMvc();
        GlobalProperties.DBConnection = con;//DBConnection is a user defined static property of GlobalProperties class
    }
    
  2. GlobalProperties.DBConnection类中使用Context属性。

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {  
              optionsBuilder.UseSqlServer(GlobalProperties.DBConnection);
        }
    }
    

答案 7 :(得分:0)

我了解这已被标记为已回答,但是当我在一个项目中将自己的 EF核心数据访问层放在一个与.DLL项目分开的项目中时,我遇到了一个问题我项目的其余部分,API,Auth和Web以及大多数人都希望我的其他项目引用此Data项目。而且我不想每次都进入Data项目更改连接字符串。

步骤1:将其包含在OnConfiguring方法中

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
      {
           var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
           IConfigurationRoot configuration = new ConfigurationBuilder()
                **.SetBasePath(Path.Combine(Directory.GetCurrentDirectory()))**
                .AddJsonFile("appsettings.json", optional: false)
                .AddJsonFile($"appsettings.{envName}.json", optional: false)
                .Build();
           optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
      }

注意:.SetBasePath(Path.Combine(Directory.GetCurrentDirectory())) 由于ASP.NET CORE足够聪明,可以选择正确的文件,因此这将使将文件复制到目录的需求无效或无效。同样,假设选择了Prod环境文件,则在为发布或生产版本构建时,指定的环境也会选择正确的文件。

第2步:创建appsettings.json

{
"ConnectionStrings": {       
  "DefaultConnection": "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"        
} 

}

请:参考:Microsoft.Extensions.Configuration

答案 8 :(得分:0)

我不太了解,但是您可以使用回调类,创建hostbuilder并将配置设置为静态属性。

对于asp core 2.2:

def itemGrabber(url):
    items = driver.find_elements_by_class_name('product')
    print(str(len(items)) + " items found on page.")

    for i in items:
        ## name of product
        t = i.find_element_by_class_name('product-description__title').text.replace("\xad", "")

        ## price
        p = i.find_element_by_class_name('product-price').text
        writer.writerow((t, p))


products = itemGrabber(url)

因此,现在您只需在需要的其他任何类上使用静态的 Program.Configuration

答案 9 :(得分:0)

如果您需要在其他层:

创建一个静态类,并在该层上公开所有配置属性,如下所示:

using Microsoft.Extensions.Configuration;
using System.IO;

namespace Core.DAL
{
    public static class ConfigSettings
    {
        public static string conStr1 { get ; }
        static ConfigSettings()
        {
            var configurationBuilder = new ConfigurationBuilder();
            string path = Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json");
            configurationBuilder.AddJsonFile(path, false);
            conStr1 = configurationBuilder.Build().GetSection("ConnectionStrings:ConStr1").Value;
        }
    }
}