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)不传参数

b8024483a18fcfac5bf068b94c451ddc.png

47982d724a860c8062063660806349c8.png

2)传入参数

b29131b21adb5b4c57eee721a62a13f8.png

29b9364257c1cc64a4e8b4ead46968fd.png

传参的格式有多种:

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

}

}

测试图:

09e962b3d9c84dcc0ef81fd1e5147238.png

ecdfd08a58da0bf2e2b2e22749eb74f4.png

两种情况都会显示

32cf8ec20d8c39c999286dbd4c3d095e.png

实际上,在 2.X 版本,CreateDefaultBuilder(args) 方法内部已经调用了 AddCommandLine(args) 方法,我们不需要再调一次了.源码(部分)如下:

b70229c22351ebb93bbb9b87bdeeef9a.png

二.环境变量配置提供程序 : AddEnvironmentVariables

在 2.X 版本,CreateDefaultBuilder(args) 方法内部已经调用了 AddEnvironmentVariables() 方法,我们不需要再调一次了.源码(部分)如下:

d7e0e24f59f7f45973d446daf948111c.png

其实,红框框起来的方法都是配置提供程序.

那么,环境变量到底有哪些呢?哪里可以看呢?

新建如下控制器:

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

}

}

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

8f1e8614c027b4f51d45c908a1a25c64.png

我们试试查询红框标注的环境变量:

739324cdf28160b65da1fcbd874e1cb7.png

三.文件配置提供程序 : 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"}

}

请求结果:

6767218dc606eb47c9e55f1ffdb9123c.png

下面我们来创建自己的配置文件:

在当前项目下新建一个 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");

}

}

c60a2b62ad91b6646b09b8b94c5b82da.png

五. 内存配置提供程序  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();

}

6d9c2188c032e52d902c09f9e7aac20c.png

六.自定义配置提供程序

该示例演示了如果使用EF创建从数据库(MySql)读取配置的提供程序.

第一步:安装 MySqlEF

489150c6e8e99dbd2a2f96de6c549e12.png

第二步:创建数据库表:

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)查询所有,可以看到,我们新增的配置数据已经加到系统中了;(看右边的滚动条就知道总共有很多很多配置...)

3c80aa602ad28266eb026a35bf49fd61.png

2)查询特定key

56111ce171769a9043eaa2c343a30233.png

如果使用该方式提供配置数据,需要注意以下两点:

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

}

}

调用结果:

6eb72b02bd3552ceed01fe4b575897c6.png

但是这种方式,个人持反对态度,因为存储在系统中的配置数据有很多很多,上述方法相当于读取所有配置数据来反序列化.

三.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") 来获取.

14283c080d83c1acdfcf9d5ef24a84cc.png

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

a84167fee0e77ee3a6b1c7702c31883c.png

因此,要通过该方法把上述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);

}

58d9304ddc50c86e048e6ac14742d6d9.png

貌似完了.

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包:

27c952b02e00407d64441888c34432e2.png

创建一个 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();

}

}

}

图就不上了.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值