一般来说,Asp .NetCore 应用从官方默认的appsetting.json文件中读取就好,而且利用option模式中的 IOptionsSnapSot<T>、IOptionsMonitor<T>可以动态加载配置,你可以直接修稿json文件来保证。但是这样也有一定的不方便之处:你的配置放在单个json文件,加入你的为服务项目有10个,如果因为项目需求变了,要更改配置,就要到10个json文件中修改,而如果这10个项目的配置都在一个数据库中,那么只需一个脚本就能改好了。

不过要从数据库动态同步加载需要做一些额外的工作,本节就先介绍静态加载数据库配置。

目录

1.搭建基本框架

a. 创建asp .netcore 项目

b.创建实体类,数据文上下文类

c.添加数据库连接信息

d.迁移、更新数据库

2.编写自定义配置源

2.1 实现ConfigurationProvider类

2.2 ConfigurationSource

2.3 配置ConfigureAppConfiguration



1.搭建基本框架

由于这里不是重点,因此只是简单的介绍关键步骤,如果有不懂的具体可以看此.NET 6.0 - Connect to MySQL Database with Entity Framework Core,有详细讲解。

a. 创建asp .netcore 项目

可以创建webApi项目也可以创建MVC项目。由于使用的是MySql和EFcore,因为项目要添加下面三个包:

Pomelo.EntityFrameworkCore.MySql
Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools

 b.创建实体类,数据文上下文类

实体类保存我们要的配置信息,参考json文件,我们保存为Key-Value模式:

    public class ConfigurationEntity{[Key]public string Key { get; set; }public string Value { get; set; }}

然后创建数据库上下文类:

    public class ConfigurationDbContext:DbContext{public ConfigurationDbContext(DbContextOptions options):base(options)  { }public DbSet<ConfigurationEntity>? configurationEntities { get; set; }}

c.添加数据库连接信息

一般情况我们可以将数据库的链接配置放到appsettings.json文件中,不过有时候我们不想让用户修改,可以放到机密文件中,机密文件(secret.json)也是asp框架下默认的读取文件之一,其加载顺序在appsettings.json之后,也就是如果你在两个json中都配置了ConnectionString,根据后来居上的法则,secret.json会生效。具体操作如下:

在解决方案资源管理器窗口,在你当前项目上右键,弹出菜单中选择“管理用户机密

选择之后就会弹出secrets.json 编辑页面,和appsettings.json同样配置即可:

然后就可以将我们的数据库上下文类(DbContex)配置到服务中:

builder.Services.AddDbContext<ConfigurationDbContext>(opts =>opts.UseMySql(ConnectionString, ServerVersion.AutoDetect(ConnectionString)));

 d.迁移、更新数据库

编译项目所在的整个解决方案,没有bug后(这点很重要,否则会迁移报错),先迁移数据,

迁移”(migration)是指根据实体类,生成数据库表的操作,迁移在Code First(模型驱动开发)很常见,区别于早期的先在数据库建表的“数据驱动开发”(Database First).

EFCore迁移很简单:执行命令:

Add-Migration InitXXXXX

执行没问题后,执行更新数据库命令:

Update-Database

你就会在你链接的数据库上看到你新建的表,表名为你ConnectionStrings中定义。


2.编写自定义配置源

asp.net core官方不支持直接从数据库中读取配置,所以这里我们要自定义配置。而自定义配置都需要实现IConfigurationProvider接口,也就是真正将数据库的字段构建成Dictionary<>。一般我笨都直接集成ConfigurationProvider这个抽象类,ConfigurationProvider中最重要的方法就是Load,自定义配置提供者要实现Load方法来加载配置数据,返回的就是IDictionary<string,string>,这个字典保存在“Data”属性中,而且还遵循“多层级数据扁平化“规范,如果配置发生了改变,则需要调用ReLoad方法来通知监听配置改变的代码。

2.1 实现ConfigurationProvider类

 public class EFConfigurationProvider:ConfigurationProvider{public Action<DbContextOptionsBuilder> _optionsAction;public EFConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction){_optionsAction = optionsAction;}public override void Load(){var builder = new DbContextOptionsBuilder<ConfigurationDbContext>();_optionsAction(builder);using var dbContext = new ConfigurationDbContext(builder.Options);dbContext.Database.EnsureCreated();Data=!dbContext.configurationEntities!.Any()?CreateAndSaveDefaultValues(dbContext):dbContext.configurationEntities?.ToDictionary(c=>c.Key,c=>c.Value);}private static IDictionary<string,string> CreateAndSaveDefaultValues(ConfigurationDbContext context){var configValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase){{ "Pages:HomePage:WelcomeMessage", "Welcome to the ProjectConfigurationDemo Home Page" },{ "Pages:HomePage:ShowWelcomeMessage", "true" },{ "Pages:HomePage:Color", "black" },{ "Pages:HomePage:UseRandomTitleColor", "true" }};context.configurationEntities?.AddRange(configValues.Select(kvp => new ConfigurationEntity{Key = kvp.Key,Value = kvp.Value}).ToArray());context.SaveChanges();return configValues;}}

简单说一下,在构造函数中,需要传递一个Action<DbContextOptionsBuilder>对象,因为我们要在Load函数中链接数据库,所以需要提供连接数据的的信息,当然可以直接加载:

  public class EFConfigurationProvider2 : ConfigurationProvider{private readonly IConfiguration _configuration;public EFConfigurationProvider2(IConfiguration configuration){_configuration = configuration;}public override void Load(){using var dbContext = new ConfigurationDbContext(CreateDbContextOptions());dbContext.Database.EnsureCreated();Data = !dbContext.configurationEntities!.Any()? CreateAndSaveDefaultValues(dbContext) : dbContext.configurationEntities?.ToDictionary(c => c.Key, c => c.Value);}private DbContextOptions<ConfigurationDbContext> CreateDbContextOptions(){var connectionString = _configuration.GetConnectionString("MySql");return new DbContextOptionsBuilder<ConfigurationDbContext>().UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)).Options;}private static IDictionary<string, string> CreateAndSaveDefaultValues(ConfigurationDbContext context){var configValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase){{ "Pages:HomePage:WelcomeMessage", "Welcome to the ProjectConfigurationDemo Home Page" },{ "Pages:HomePage:ShowWelcomeMessage", "true" },{ "Pages:HomePage:Color", "black" },{ "Pages:HomePage:UseRandomTitleColor", "true" }};context.configurationEntities?.AddRange(configValues.Select(kvp => new ConfigurationEntity{Key = kvp.Key,Value = kvp.Value}).ToArray());context.SaveChanges();return configValues;}}

本质就是,需要将数据库的链接信息传递到DbContextOptions<ConfigurationDbContext> ,以供

ConfigurationDbContext使用。

在Load函数中,我们会判断数据中是否有数据,如果没有,则添加一点默认数据,否则加载新的数据并转化为字典类型。

2.2 ConfigurationSource

有了配置提供者,我们就能编写配置源,服务加载不同的配置总是加载不同的配置源而不是配置提供者,IConfigurationSource中要实现Builder方法返回的就是IConfigurationProvider.

    public class EFConfigurationSource : IConfigurationSource{private readonly Action<DbContextOptionsBuilder> _optionsAction;public EFConfigurationSource(Action<DbContextOptionsBuilder> optionsAction){_optionsAction = optionsAction;}public IConfigurationProvider Build(IConfigurationBuilder builder){return new EFConfigurationProvider(_optionsAction);}}

2.3 配置ConfigureAppConfiguration

一切就绪,我们在ConfigureAppConfiguration配置,也就是将我们编写的配置源加载进去

var builder = WebApplication.CreateBuilder(args);
var ConnectionString = builder.Configuration.GetConnectionString("MySql");
builder.Host.ConfigureAppConfiguration((_, configBuilder) =>
{var config = configBuilder.Build();var configSource = new EFConfigurationSource(opts =>opts.UseMySql(ConnectionString, ServerVersion.AutoDetect(ConnectionString)));configBuilder.Add(configSource);
});

至此,在执行:

var app = builder.Build();

后,配置中就能使用读取了数据库的配置了,不过在这里,我们要删除下面的代码,因为已经不需要了:

//builder.Services.AddDbContext<ConfigurationDbContext>(opts =>
//    opts.UseMySql(ConnectionString, ServerVersion.AutoDetect(ConnectionString)));

运行后就发现,数据库中多了一些我们在CreateAndSaveDefaultValues函数中提供的默认几组数据:

为了进一步验证读取,我们又加了两条数据,并根据配置扁平化处理,用“:”隔开,这样等价于appsettings.json中:

"Wang":{"Age":23,"Name":"xiao wang"
}

然后对应的实体类:

    public class Student{public string? Name { get; set; }public int Age { get; set; }}

最后读取,并打印:

var app = builder.Build();
var wang = app.Services.GetRequiredService<IOptions<Student>>().Value;
Console.WriteLine($"{wang.Name}---{wang.Age}");

控制台上就有了我们要的数据。


至此从数据库加载数据的基本操作就完成了,其实从数据库中家在配置,在官方文档中有详细教程:Custom configuration provider,不过这个教程也没有实现动态更新配置,根据前面绿色背景的文字,倒是提供了思路,我在下一节将实现动态更新配置。

Asp .NetCore 从数据库加载配置(一)相关推荐

  1. Spring 3.1 –从数据库加载XML配置的属性

    Spring使通过其PropertyPlaceholderConfigurer和(Spring 3.1之前)PropertySourcesPlaceholderConfigurer(Spring 3. ...

  2. 魔方APP项目-02-服务端项目搭建,创建manage.py文件、构建全局初始化函数创建app应用对象、通过终端脚本启动项目、项目加载配置、数据库初始化、日志初始化、蓝图初始化

    服务端项目搭建 新建项目目录mofangapi,并创建虚拟环境 mkvirtualenv mofang 安装开发中使用的依赖模块 pip install flask==0.12.4 pip insta ...

  3. 大话PHP设计模式:类自动载入、PSR-0规范、链式操作、11种面向对象设计模式实现和使用、OOP的基本原则和自动加载配置...

    一.类自动载入 SPL函数 (standard php librarys) 类自动载入,尽管 __autoload() 函数也能自动加载类和接口,但更建议使用 spl_autoload_registe ...

  4. java自定义上下文对象_Java框架_Spring应用上下文对象加载配置

    我们都知道IOC是spring框架的核心,主要作用是控制反转,把我们需要的对象从容器中提供给我们,但是IOC是如何加载我们所需要的对象的? Spring容器是IOC容器的一种,它通过Applicati ...

  5. springboot 加载配置信息(静态)

    springboot 加载配置信息(静态) 举例:动态设置验证码过期时间 application-uat.properties配置(文件路径:/src/main/resources/applicati ...

  6. logstash 自动重新加载配置

    自动重新加载配置 为了可以自动检测配置文件的变动和自动重新加载配置文件,需要在启动的时候使用以下命令: ./bin/lagstash -f configfile.conf --config.reloa ...

  7. Windows PE 第十章 加载配置信息

    加载配置信息 加载配置信息最初最用在Windows NT操作系统中,作为文件头部的延伸部分,后来被用作异常处理.加载配置信息表中存放了基于结构化异常处理(SEH)技术的各项异常句柄.当程序运行发生异常 ...

  8. Python+selenium 自动化-启用带插件的chrome浏览器,调用浏览器带插件,浏览器加载配置信息。

    正常的话我们启用的 chrome 浏览器是不带插件的,如果你能登陆 chrome 的话,你会发现登陆信息也没有,还有不管你怎样设置每次新打开的 chrome 都是默认设置的. 我们正常启动的浏览器每次 ...

  9. PE学习(十)第十章: 加载配置信息表

    第十章:加载配置信息 加载配置信息表最初是用来存放附加信息,后来用来存放SEH各种导演句柄变成"异常处理表" 异常与中断类似,中断有点外部(键盘)发出,异常由软件,异常发生时跑到异 ...

最新文章

  1. 从消费端到企业端,从设备到数据:物联网市场的爆发式增长
  2. 从零开始入门 K8s | K8s 的应用编排与管理
  3. linux postgres用户,关于linux:在启动时创建postgres用户
  4. 指向函数的指针--转
  5. 于企业而言,Linux 与 Windows 哪个更安全?
  6. XGB 调参基本方法
  7. 利用管道实现进程间通信
  8. ADT17中引入外部JAR包时出现ClassNotFoundException
  9. CSS中的position定位
  10. 采用python解决实际问题_Python编程语言解决几种常见的实际问题
  11. 死磕 java同步系列之开篇
  12. 生信宝典周报 | 我们有可能会被44种动物传染上新冠?
  13. 如何升级PowerShell
  14. 搜索引擎学习笔记001---lucene简明介绍
  15. 如何ajax上传文件,如何实现Ajax文件上传功能
  16. Talk预告 | 港科大(广州)助理教授王泽宇: 提升数字内容创作中的创意实现与迭代过程
  17. 关于c语言图书管理系统的ppt,课件C语言图书管理系统代码.doc
  18. 概率论考点之排列与组合
  19. 利用win7漏洞进行系统登录密码破解
  20. 线索二叉树中序非递归线索化以及递归线索化构建和遍历算法

热门文章

  1. JavaScript——优先级队列
  2. JSTL的jar包问题
  3. 关于重绘repaint和重排reflow
  4. iOS安全攻防之越狱设备检测
  5. DotNetBar Ribbon 汉化
  6. 逾期率飙升如何破?揭秘金融科技如何化解消费金融行业风险
  7. 线性八叉树_八叉树OcTree
  8. python ndarray合并_Python干货-Numpy的ndarray的合并与分割
  9. python的安装目录配置到环境变量的path当中_【转】python 环境变量配置
  10. 屏幕无法设置为指定的行数_编织技巧,教你要起多少针,超级详细的教程,不用为织毛衣发愁了...