簡體   English   中英

從 appsettings.json 獲取 ConnectionString 而不是在 .NET Core 2.0 App 中硬編碼

[英]Get ConnectionString from appsettings.json instead of being hardcoded in .NET Core 2.0 App

我有以下 class in.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 2.0 中是必需的。
升級到 ASP.NET Core 2.0 后無法創建遷移

我不想在 2 個地方(這里和 appsettings.json 中)有 ConnectionString,但只在 .json 中,所以我嘗試替換

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

ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString

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

更新 1:
請注意,顯式添加 .json 在 Core 2 中不是必需的,因此問題不在於文件。
https://andrewlock.net/exploring-program-and-startup-in-asp.net-core-2-preview1-2/

更新 2:
此外,我已經在使用 Configuration 將 ConnectionString 從 .json 發送到 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);
}

第 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 獲取)。

在 ASPNET Core 中,您可以在Startup.cs中執行此操作

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

您的連接在appsettings.json中定義

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

來自MS 文檔的示例

上面的解決方案和 Microsoft 文檔中都缺少一些東西。 如果您按照從上述文檔鏈接到 GitHub 存儲庫的鏈接,您會找到真正的解決方案。

我認為混淆在於許多人使用的默認模板包含 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 所需的。

我知道這已被標記為已回答,但我在處理一個項目時遇到了一些問題,我的 .DLL 項目中的EF Core 數據訪問層<\/strong>與我的項目的其余部分、API、Auth 和Web 和大多數人都會喜歡我的其他項目來引用這個 Data 項目。 而且我不想每次都進入 Data 項目來更改連接字符串。

第 1 步:將其包含在 OnConfiguring 方法中<\/strong>

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

將它作為 dp 注入傳遞給該類怎么樣? 在配置服務中:

services.Configure<MyOptions>(Configuration);

實際上,您可以使用默認模式來實現此結果,而無需實現IDesignTimeDbContextFactory<\/code>並進行任何配置文件復制。

此文檔<\/a>中對此進行了詳細說明,其中還討論了框架在設計時嘗試實例化DbContext<\/code>的其他方式。

具體來說,您利用了一個新的鈎子,在本例中是一個形式為public static IWebHost BuildWebHost(string[] args)<\/code>的靜態方法。 文檔另有說明,但此方法可以存在於包含您的入口點的任何類中( 請參閱 src<\/a> )。 實現這一點是1.x 到 2.x 遷移文檔<\/a>中指南的一部分,從代碼中看並不完全明顯的是,對WebHost.CreateDefaultBuilder(args)<\/code>的調用是在默認情況下連接您的配置新項目開始的模式。 這就是讓設計時服務(如遷移)使用的配置所需的全部內容。

這里有更多關於那里發生的事情的詳細信息:

在添加遷移時,當框架嘗試創建DbContext<\/code>時,它最后,它在程序集中查找<\/a>任何DbContext<\/code>派生類,並創建一個工廠方法,該方法只調用Activator.CreateInstance<\/code>作為最終的 hail mary。

框架使用的優先順序與上述相同。 因此,如果您實現了IDesignTimeDbContextFactory<\/code> ,它將覆蓋上面提到的鈎子。 不過,對於最常見的場景,您不需要IDesignTimeDbContextFactory<\/code> 。

您也可以在 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));
  1. 將以下代碼添加到startup.cs<\/code>文件中。

  2. Context<\/code>類中使用GlobalProperties.DBConnection<\/code>屬性。

我知道這並不奇怪,但您可以使用回調類,創建主機構建器並將配置設置為靜態屬性。

對於 asp 核心 2.2:

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using System;

namespace Project
{
    sealed class Program
    {
        #region Variables
        /// <summary>
        /// Last loaded configuration
        /// </summary>
        private static IConfiguration _Configuration;
        #endregion

        #region Properties
        /// <summary>
        /// Default application configuration
        /// </summary>
        internal static IConfiguration Configuration
        {
            get
            {
                // None configuration yet?
                if (Program._Configuration == null)
                {
                    // Create the builder using a callback class
                    IWebHostBuilder builder = WebHost.CreateDefaultBuilder().UseStartup<CallBackConfiguration>();

                    // Build everything but do not initialize it
                    builder.Build();
                }

                // Current configuration
                return Program._Configuration;
            }

            // Update configuration
            set => Program._Configuration = value;
        }
        #endregion

        #region Public
        /// <summary>
        /// Start the webapp
        /// </summary>
        public static void Main(string[] args)
        {
            // Create the builder using the default Startup class
            IWebHostBuilder builder = WebHost.CreateDefaultBuilder(args).UseStartup<Startup>();

            // Build everything and run it
            using (IWebHost host = builder.Build())
                host.Run();
        }
        #endregion


        #region CallBackConfiguration
        /// <summary>
        /// Aux class to callback configuration
        /// </summary>
        private class CallBackConfiguration
        {
            /// <summary>
            /// Callback with configuration
            /// </summary>
            public CallBackConfiguration(IConfiguration configuration)
            {
                // Update the last configuration
                Program.Configuration = configuration;
            }

            /// <summary>
            /// Do nothing, just for compatibility
            /// </summary>
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                //
            }
        }
        #endregion
    }
}

如果您需要不同的圖層:

創建一個靜態類並公開該層上的所有配置屬性,如下所示:

只需使用

string connectionString =
     builder.Configuration.GetConnectionString("TestDBConnectionString");

如果您使用的是“頂級語句”,則可以按如下方式獲取連接字符串:

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
        var builder = WebApplication.CreateBuilder();
        string conStr = builder.Configuration.GetConnectionString("myDb1");
        SqlConnection conn = new SqlConnection(conStr);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM