asp.net core 將配置文件配置遷移到數據庫(一)
Intro
asp.net core 配置默認是項目根目錄下的 appsettings.json 文件,還有環境變量以及 command line arguments,有一些鏈接字符串等信息可能放在數據庫里更好一些,也方便修改與維護,有的配置可能多個應用共享一些配置,這樣維護在數據庫里可能就只需要配置一次。有人可能說那你為什么不直接搞個配置中心呢,開始是想直接接入一個配置中心,后來覺得項目不大可以不必引入配置中心,直接自己造個輪子從數據庫讀取配置就可以了,於是就想自己實現一套基於數據庫的 ConfigurationProvider
探索 Configuration
Configuration 源碼在 https://github.com/aspnet/Extensions/tree/master/src/Configuration
微軟也提供了一些自己實現的 ConfigurationProvider
自定義基於 EF 的 ConfigurationProvider
需要實現兩個接口
- 實現
IConfigurationProvider
接口
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace WeihanLi.Configuration.EntityFramework
{
internal class EntityFrameworkConfigurationProvider : ConfigurationProvider
{
private readonly DbContextOptions<ConfigurationsDbContext> _dbContextOptions;
public EntityFrameworkConfigurationProvider(DbContextOptions<ConfigurationsDbContext> dbContextOptions)
{
_dbContextOptions = dbContextOptions;
}
public override void Load()
{
using (var dbContext = new ConfigurationsDbContext(_dbContextOptions))
{
var configurations = dbContext.Configurations.AsNoTracking()
.ToArray();
if (configurations.Length == 0)
return;
foreach (var configuration in configurations)
{
Data[configuration.Key] = configuration.Value;
}
}
}
}
}
- 實現
IConfigurationSource
接口
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace WeihanLi.Configuration.EntityFramework
{
internal class EntityFrameworkConfigurationSource : IConfigurationSource
{
private readonly Action<DbContextOptionsBuilder<ConfigurationsDbContext>> _action;
public EntityFrameworkConfigurationSource(Action<DbContextOptionsBuilder<ConfigurationsDbContext>> action)
{
_action = action;
}
private readonly DbContextOptionsBuilder<ConfigurationsDbContext> DbContextOptionsBuilder = new DbContextOptionsBuilder<ConfigurationsDbContext>();
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
_action.Invoke(DbContextOptionsBuilder);
return new EntityFrameworkConfigurationProvider(DbContextOptionsBuilder.Options);
}
}
}
擴展方法:
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace WeihanLi.Configuration.EntityFramework
{
public static class RedisConfigurationExtension
{
/// <summary>
/// Adds an <see cref="IConfigurationProvider"/> that reads configuration values from EntityFramework.
/// </summary>
/// <param name="builder">The <see cref="IConfigurationBuilder"/> to add to.</param>
/// <param name="action">Configures the configurationsDbContext source.</param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddEntityFramework(this IConfigurationBuilder builder, Action<DbContextOptionsBuilder<ConfigurationsDbContext>> action)
=> builder.Add(new EntityFrameworkConfigurationSource(action));
}
}
使用
修改 Program 文件 WebHost 的構建,參考https://github.com/WeihanLi/AspNetCorePlayground/blob/ecb461f209db7cf73d8285806473519301f76444/TestWebApplication/Program.cs:
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(configBuilder =>
{
var configuration = configBuilder.Build();
configBuilder.AddEntityFramework(config => config.UseSqlServer(configuration.GetConnectionString("Configurations"));
})
.UseStartup<Startup>();
源碼
你可以修改源碼來進一步定制符合你需要的基於數據庫的 ConfigurationProvider