天天看點

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

先上一段代碼,了解一下 .NET Core 配置資料的結構.

建立一個 控制台項目,添加一個檔案 json.json ,檔案内容如下:

{"country": "cn","person": {"id": 1,"address": {"addName": "chengdu"}

}

}

控制台代碼:

private static void Main(string[] args)

{

ConfigurationBuilder builder= newConfigurationBuilder();

builder.AddJsonFile(path:@"E:\xxx\my\core\VS2017\MyConfig\Demo2\json.json", optional: false, reloadOnChange: true);

IConfigurationRoot config=builder.Build();

Console.WriteLine(config["country"]);//cn

Console.WriteLine(config["person:id"]);//1

Console.WriteLine(config["person:address:addname"]);//chengdu

Console.ReadKey();//修改 json.json 檔案中 "id":2

Console.WriteLine(config["person:id"]);//2

Console.ReadKey();

}

AddJsonFile 方法有多個重載,上面隻給出了其中一個,3個參數分别表示:

path:檔案的實體路徑;

optional: xml 文檔是這樣寫的:Whether the file is optional. 該檔案是否可選.true 表示可選,即如果該檔案不存在,不會抛出異常,下面的所有顯示都為空;false 表示不可選,即如果該檔案不存在,會抛出異常.

reloadOnChange:如果檔案修改了,是否重新加載.

配置提供程式

ASP.NET Core 常用的共有6種配置提供程式 :

指令行配置提供程式

環境變量配置提供程式

檔案配置提供程式

Key-per-file配置提供程式

記憶體配置提供程式

自定義配置提供程式

一.指令行配置提供程式 :AddCommandLine

1.建立一個 WebAPI 項目,建立一個 TestController

[Route("api/[controller]")]

[ApiController]public classTestController : ControllerBase

{private readonlyIConfiguration _config;publicTestController(IConfiguration configuration)

{

_config=configuration;

}public stringGet()

{//讀取配置資料中 Key 為 CommandLineKey 的值,如果沒有這個 Key,則傳回預設值: defaultValue

//讀取配置檔案的方法後面會單獨講.

return _config.GetValue("CommandLineKey","defaultValue");

}

}

2.修改 CreateWebHostBuilder 方法

public classProgram

{public static void Main(string[] args)

{

CreateWebHostBuilder(args).Build().Run();

}public static IWebHostBuilder CreateWebHostBuilder(string[] args)

{var config = newConfigurationBuilder().AddCommandLine(args).Build();var hostBuilder =WebHost.CreateDefaultBuilder(args);return hostBuilder.UseConfiguration(config).UseStartup();

}

}

3.測試:

1)不傳參數

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)
efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

2)傳入參數

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)
efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

傳參的格式有多種:

dotnet run CommandLineKey1=Value1

dotnet run --CommandLineKey2=Value2

dotnet run --CommandLineKey3 Value3

dotnet run /CommandLineKey4=Value4

dotnet run /CommandLineKey5 Value5

此外,傳入的以單橫杠"-"或者雙橫杠"--"作為字首的 Key 支援替換:

public classProgram

{public static void Main(string[] args)

{

CreateWebHostBuilder(args).Build().Run();

}public static IWebHostBuilder CreateWebHostBuilder(string[] args)

{

Dictionary switchMapping = new Dictionary{

{"-key", "CommandLineKey"},

{"--key", "CommandLineKey"},

};

IConfigurationRoot config= newConfigurationBuilder().AddCommandLine(args, switchMapping).Build();return WebHost.CreateDefaultBuilder().UseConfiguration(config).UseStartup();

}

}

測試圖:

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)
efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

兩種情況都會顯示

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

實際上,在 2.X 版本,CreateDefaultBuilder(args) 方法内部已經調用了 AddCommandLine(args) 方法,我們不需要再調一次了.源碼(部分)如下:

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

二.環境變量配置提供程式 : AddEnvironmentVariables

在 2.X 版本,CreateDefaultBuilder(args) 方法内部已經調用了 AddEnvironmentVariables() 方法,我們不需要再調一次了.源碼(部分)如下:

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

其實,紅框框起來的方法都是配置提供程式.

那麼,環境變量到底有哪些呢?哪裡可以看呢?

建立如下控制器:

[Route("api/[controller]/[action]")]

[ApiController]public classTestController : ControllerBase

{private readonlyIConfiguration _config;publicTestController(IConfiguration configuration)

{

_config=configuration;

}public IEnumerable>GetAll()

{return_config.AsEnumerable();

}public string Get(stringkey)

{return _config.GetValue(key, "defaultValue");

}

}

太多了,隻截了其中一小部分:

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

我們試試查詢紅框标注的環境變量:

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

三.檔案配置提供程式 : AddJsonFile , AddIniFile , AddXmlFile

以 AddJsonFile 為例講解,其他兩個都差不多.

從上面的源碼截圖中我們已經看到,在使用 CreateDefaultBuilder 方法初始化新的 WebHostBuilder 時,會自動調用 AddJsonFile 兩次,依次從下面兩個檔案加載配置:

appsettings.json : 首先讀取該檔案.

appsettings.{Environment}.json : 再讀取此檔案,該檔案中的配置會替代 appsettings.json 檔案中的值.

示例: (紅色部分是自己加的)

appsettings.json:

{"Logging": {"LogLevel": {"Default": "Warning"}

},"AllowedHosts": "*","FirstSection": {

"SecondSection": "hello world"}

}

appsettings.{Environment}.json:

{"Logging": {"LogLevel": {"Default": "Debug","System": "Information","Microsoft": "Information"}

},"FirstSection": {

"SecondSection": "fuck u"}

}

請求結果:

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

下面我們來建立自己的配置檔案:

在目前項目下建立一個 jsonconfig.json 檔案:

{"id": 1,"name": "wjire"}

CreateWebHostBuilder 方法修改如下:

public static IWebHostBuilder CreateWebHostBuilder(string[] args)

{

IWebHostBuilder hostBuilder=WebHost.CreateDefaultBuilder(args);return hostBuilder.ConfigureAppConfiguration((context, builder) =>{

builder.AddJsonFile(Path.Combine(context.HostingEnvironment.ContentRootPath,"jsonconfig.json"),true, true);

}).UseStartup();

}

圖就不上了...

附:

AddIniFile 配置檔案:

[section0]

key0=value

key1=value

[section1]

subsection:key=value

[section2:subsection0]

key=value

[section2:subsection1]

key=value

AddXmlFile 配置檔案

value

value

value

value

四.Key-per-file 配置提供程式  AddKeyPerFile

這個提供程式有點特别,它是将檔案名(含擴充名)作為 Key,檔案内容作為 Value.

示例:

在目前項目下建立一個 filename.txt 檔案,檔案内容就一句話: hello world

public static IWebHostBuilder CreateWebHostBuilder(string[] args)

{

IWebHostBuilder hostBuilder=WebHost.CreateDefaultBuilder(args);return hostBuilder.ConfigureAppConfiguration((context, builder) =>{//param1:檔案所在目錄的實體路徑//param2:該檔案是否可選

builder.AddKeyPerFile(context.HostingEnvironment.ContentRootPath, true);

}).UseStartup();

}

控制器如下:

[Route("api/[controller]/[action]")]

[ApiController]public classTestController : ControllerBase

{private readonlyIConfiguration _config;publicTestController(IConfiguration configuration)

{

_config=configuration;

}public string Get(stringkey)

{return _config.GetValue(key, "defaultValue");

}

}

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

五. 記憶體配置提供程式  AddInMemoryCollection

這個很簡單,直接上圖:

public static IWebHostBuilder CreateWebHostBuilder(string[] args)

{

Dictionary memoryCollection = new Dictionary{

{"id","1"},

{"name","wjire"}

};

IWebHostBuilder hostBuilder=WebHost.CreateDefaultBuilder(args);return hostBuilder.ConfigureAppConfiguration((context, builder) =>{

builder.AddInMemoryCollection(memoryCollection);

}).UseStartup();

}

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

六.自定義配置提供程式

該示例示範了如果使用EF建立從資料庫(MySql)讀取配置的提供程式.

第一步:安裝 MySqlEF

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

第二步:建立資料庫表:

CREATE TABLE `myconfigs` (

`Id` varchar(20) NOT NULL DEFAULT '',

`value` varchar(20) NOT NULL DEFAULT '',

PRIMARY KEY (`Id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

第三步:建立實體類

public classMyConfig

{public string Id { get; set; }public string Value { get; set; }

}

第四步:建立資料庫上下文

public classMyConfigContext : DbContext

{public MyConfigContext(DbContextOptions options) : base(options)

{

}public DbSet MyConfigs { get; set; }

}

第五步:建立配置資料源

public classMyConfigSource : IConfigurationSource

{private readonly Action_optionsAction;public MyConfigSource(ActionoptionsAction)

{

_optionsAction=optionsAction;

}publicIConfigurationProvider Build(IConfigurationBuilder builder)

{return newMyConfigProvider(_optionsAction);

}

}

第六步:建立配置資料源提供器

public classMyConfigProvider : ConfigurationProvider

{private Action OptionsAction { get; }public MyConfigProvider(ActionoptionsAction)

{

OptionsAction=optionsAction;

}//從資料庫讀取配置

public override voidLoad()

{

DbContextOptionsBuilder builder = new DbContextOptionsBuilder();

OptionsAction(builder);using (MyConfigContext dbContext = newMyConfigContext(builder.Options))

{//Data 是基類 ConfigurationProvider 的屬性,用來存儲配置資料源的.

Data = !dbContext.MyConfigs.Any()//判斷表是否有資料

? CreateAndSaveDefaultValues(dbContext)//如果沒有資料,則添加一些資料,存儲到配置資料源中.

: dbContext.MyConfigs.ToDictionary(c => c.Id, c => c.Value);//如果有資料,讀取出來,存儲到配置資料源中.

}

}private static IDictionaryCreateAndSaveDefaultValues(MyConfigContext dbContext)

{

Dictionary configValues = new Dictionary{

{"1", "refuge"},

{"2", "36"},

{"3", "chengdu"}

};

dbContext.MyConfigs.AddRange(configValues.Select(kvp=> newMyConfig

{

Id=kvp.Key,

Value=kvp.Value

}).ToArray());

dbContext.SaveChanges();returnconfigValues;

}

}

第七步:建立擴充方法,對外公開自定義的資料提供程式

public static classMyConfigExtension

{public static IConfigurationBuilder AddCustomConfigurationProviderApp(this IConfigurationBuilder builder, ActionoptionsAction)

{return builder.Add(newMyConfigSource(optionsAction));

}

}

第八步:建立測試用的控制器

[Route("api/[controller]/[action]")]

[ApiController]public classTestController : ControllerBase

{private readonlyIConfiguration _config;publicTestController(IConfiguration configuration)

{

_config=configuration;

}//查詢所有

public IEnumerable>GetAll()

{return_config.AsEnumerable();

}//查詢某個key

public string Get(stringkey)

{return _config.GetValue(key, "defaultValue");

}

}

第九步:調用自定義配置提供程式

public classProgram

{public static void Main(string[] args)

{

CreateWebHostBuilder(args).Build().Run();

}public static IWebHostBuilder CreateWebHostBuilder(string[] args)

{

IWebHostBuilder hostBuilder=WebHost.CreateDefaultBuilder(args);return hostBuilder.ConfigureAppConfiguration((context, builder) =>{

builder.AddCustomConfigurationProviderApp(options=> options.UseMySql("Server=localhost;Database=test;User=root"));

}).UseStartup();

}

}

測試結果:

1)查詢所有,可以看到,我們新增的配置資料已經加到系統中了;(看右邊的滾動條就知道總共有很多很多配置...)

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

2)查詢特定key

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

如果使用該方式提供配置資料,需要注意以下兩點:

1.提供程式在啟動時就将資料庫表讀入配置,不會基于每個key查詢資料庫;

2.應用啟動後,更新資料庫,配置不會更新.

上面講了如果提供配置資料,下面講擷取配置的幾種常用方法:

一.GetValue 上面已經示範過了,這裡不再重複.隻把常用的重載方法列出來

GetValue("key") 如果 key 不存在,則會抛異常;

GetValue("key",T default) 如果 key 不存在,則傳回預設值

二. T Get()

對于下面這個 json 檔案:

{"name": "refuge","age": 36,"address": {"city": "chengdu"}

}

定義一個實體:

public classPerson

{public string Name { get; set; }public int Age { get; set; }public Address Address { get; set; }

}public classAddress

{public string City { get; set; }

}

控制器:

[Route("api/[controller]/[action]")]

[ApiController]public classTestController : ControllerBase

{private readonlyIConfiguration _config;publicTestController(IConfiguration configuration)

{

_config=configuration;

}public stringGet()

{var person = _config.Get();returnJsonConvert.SerializeObject(person);

}

}

調用結果:

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

但是這種方式,個人持反對态度,因為存儲在系統中的配置資料有很多很多,上述方法相當于讀取所有配置資料來反序列化.

三.GetSection

講該方法之前,有必要再熟悉一下配置在系統中的存儲結構到底是怎麼樣的.

對于上面那個 json 檔案:name": "refuge",

"age": 36,"address": {"city": "chengdu"}

}

将其讀入配置後,存儲的結構如下:

{"key":"name","value":"refuge"}

{"key":"age","value":"36"}

{"key":"address","value":null} //通過查詢所有配置,确實有這一行,這意味着想通過 GetValue("address") 反序列化為對象是不可能的...

{"key":"address:city","value":"chengdu"}]

對于上面這些配置,"refuge" 和 "36" 是可以通過第一個方法 GetValue("name") , GetValue("age") 來擷取.

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

而 "chengdu" 隻能用 GetValue("address:city") 方法擷取了.

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

是以,要通過該方法把上述json檔案的内容轉成 Person 對象,則需要對 json 檔案進行修改,添加一個 "person" 節點:

{"person": {"name": "refuge","age": 36,"address": {"city": "chengdu"}

}

}

Action:

public stringGet()

{//方法一:

{

Person person= _config.GetSection("person").Get();returnJsonConvert.SerializeObject(person);

}//方法二:

{//Person person = new Person();//_config.GetSection("person").Bind(person);//return JsonConvert.SerializeObject(person);

}

}

方法一明顯要帥氣得多!

問題又來了,如果我隻想反序列化 "address" 節點的值,怎麼辦呢?下面這個方法可以完成.

四.GetChildren

Action:

public stringGet()

{

IConfigurationSection firstChildSection= _config.GetSection("person").GetChildren().First();

Address address= firstChildSection.Get

();returnJsonConvert.SerializeObject(address);

}

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

貌似完了.

2019年1月6日補充:

上面提到的全是從目前項目加載配置,ASP.NET Core 2.0 提供了從外部程式集加載配置的方法

需要實作該接口:

public interfaceIHostingStartup

{

voidConfigure(IWebHostBuilder builder);

}

示例:

建立類庫 : ExternalAssembly

namespaceExternalAssembly

{public classExternalConfig : IHostingStartup

{public voidConfigure(IWebHostBuilder builder)

{

Dictionary memoryCollection = new Dictionary{

{"id","1"},

{"name","refuge"}

};

builder.ConfigureAppConfiguration((context, configBuilder)=>{

configBuilder.AddInMemoryCollection(memoryCollection);

});

}

}

}

這裡要特别注意:

ConfigureAppConfiguration 方法需要安裝nuget包:

efcore2 mysql_ASP.NET Core 2.2 基礎知識(六) 配置(内含MySql+EF)

建立一個 WebAPI 項目,添加對上述類庫的引用,并在 Program 類中添加對該類庫的調用聲明(紅色标注):

usingMicrosoft.AspNetCore;usingMicrosoft.AspNetCore.Hosting;

[assembly: HostingStartup(typeof(ExternalAssembly.ExternalConfig))]namespaceDemo5

{public classProgram

{public static void Main(string[] args)

{

CreateWebHostBuilder(args).Build().Run();

}public static IWebHostBuilder CreateWebHostBuilder(string[] args)

{return WebHost.CreateDefaultBuilder(args).UseStartup();

}

}

}

圖就不上了.