我們在上篇和中篇對配置模型中默認提供的各種ConfigurationProvider進行了深入詳盡的介紹,如果它們依然不能滿足項目中的配置需求,我們可以還可以通過自定義ConfigurationProvider來支持我們希望的配置來源。就配置數據的持久化方式來說,將配置存儲在數據庫中應該是一種非常常見的方式,接下來我們就是創建一個針對數據庫的ConfigurationProvider,它采用最新的Entity Framework 7來完成數據庫的存取操作。
目錄
MemoryConfigurationProvider
EnvironmentVariablesConfigurationProvider
CommandLineConfigurationProvider
JsonConfigurationProvider
XmlConfiguationProvider
IniConfigurationProvider
自定義ConfigurationProvider
我們將這個自定義ConfigurationProvider命名為DbConfigurationProvider。在正式對它的實現展開介紹之前,我們先來看看它在項目中的應用。我們創建一個ASP.NET Core控制臺程序來演示對這個DbConfigurationProvider應用,由于我們需要使用到Entity Framework 7,并且采用SQL Server數據庫,所以我們需要在project.json文件中按照如下的方式添加對“EntityFramework.MicrosoftSqlServer”這個NuGet包的依賴。
1: {
2: ...
3: "dependencies": {
4: "Microsoft.Extensions.Configuration": "1.0.0-rc1-final",
5: "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final"
6: },
7: }
我們按照如下的方式讀取相關配置并將綁定為一個Profile對象。我們調用自定義的擴展方法AddDatabase創建一個DbConfigurationProvider對象并將其注冊到創建的ConfigurationBuilder對象上。我們在調用擴展方法AddDatabase的時候指定了連接的目標數據庫,同時設置了一些初始的配置項(如果確保配置項存在于目標數據庫中,這個參數是不需要指定的),它們提供了組成一個完整的Profile對象的基礎數據。
1: string connectionString = "...";
2: Profile profile = new ConfigurationBuilder().AddDatabase(optionsBuilder => optionsBuilder.UseSqlServer(connectionString),
3: new Dictionary<string, string>
4: {
5: ["Profile:Gender"] = "Male",
6: ["Profile:Age"] = "18",
7: ["Profile:ContactInfo:Email"] = "foobar@outlook.com",
8: ["Profile:ContactInfo:PhoneNo"] = "123456789"
9: })
10: .Build().Get<Profile>("Profile");
如上面的代碼片斷所示,針對自定義的DbConfigurationProvider的應用僅僅體現在我們為ConfigurationBuilder定義的擴展方法AddDatabase上,所以使用起來是非常方便的,那么這個擴展方法背后有著怎樣的邏輯實現呢?DbConfigurationProvider采用Entity Framework 7以Code First的方式進行數據操作,如下所示的ApplicationSetting是表示基本配置項的POCO類型,我們將配置項的Key以小寫的方式存儲。另一個ApplicationSettingsContext是對應的DbContext類型。
1: [Table("ApplicationSettings")]
2: public class ApplicationSetting
3: {
4: private string key;
5:
6: [Key]
7: public string Key
8: {
9: get { return key; }
10: set { key = value.ToLowerInvariant(); }
11: }
12:
13: [Required]
14: [MaxLength(512)]
15: public string Value { get; set; }
16:
17: public ApplicationSetting()
18: {}
19:
20: public ApplicationSetting(string key, string value)
21: {
22: this.Key = key;
23: this.Value = value;
24: }
25: }
26:
27: public class ApplicationSettingsContext : DbContext
28: {
29: public ApplicationSettingsContext(DbContextOptions options) : base(options)
30: {}
31:
32: public DbSet<ApplicationSetting> Settings { get; set; }
33: }
如下所示的是DbConfigurationProvider和擴展方法AddDatabase的定義。DbConfigurationProvider它的構造函數具有兩個參數,一個參數類型為Action<DbContextOptionsBuilder>,用來對創建DbContext采用的DbContextOptions進行設置,另一個可選的參數用來指定一些需要自動初始化的配置項。在重寫的Load方法中,我們利用創建的DbContexts從數據庫中讀取所有的配置項并作為自身的配置字典。
1: public class DbConfigurationProvider: ConfigurationProvider
2: {
3: public Func<DbContextOptions> DbContextOptionsAccessor { get; private set; }
4:
5: public DbConfigurationProvider(Action<DbContextOptionsBuilder> setup, IEnumerable<KeyValuePair<string, string>> settings = null)
6: {
7: DbContextOptionsBuilder<ApplicationSettingsContext> optionsBuilder = new DbContextOptionsBuilder<ApplicationSettingsContext>();
8: setup(optionsBuilder);
9: this.DbContextOptionsAccessor = () => optionsBuilder.Options;
10:
11: if (settings!=null && settings.Any())
12: {
13: using (ApplicationSettingsContext dbContext = new ApplicationSettingsContext(this.DbContextOptionsAccessor()))
14: {
15: dbContext.Database.EnsureCreated();
16: foreach (var item in settings)
17: {
18: ApplicationSetting setting = dbContext.Settings.FirstOrDefault(it => it.Key == item.Key.ToLowerInvariant());
19: if (null == setting)
20: {
21: dbContext.Settings.Add(new ApplicationSetting(item.Key, item.Value));
22: }
23: else
24: {
25: setting.Value = item.Value;
26: }
27: }
28: dbContext.SaveChanges();
29: }
30: }
31: }
32:
33: public override void Load()
34: {
35: using (ApplicationSettingsContext dbContext = new ApplicationSettingsContext(this.DbContextOptionsAccessor()))
36: {
37: var dictionary = dbContext.Settings.ToDictionary(it => it.Key, it => it.Value);
38: this.Data = new Dictionary<string, string>(dictionary, StringComparer.OrdinalIgnoreCase);
39: }
40: }
41: }
42:
43: public static class DbConfigurationProviderExtensions
44: {
45: public static IConfigurationBuilder AddDatabase(this IConfigurationBuilder builder, Action<DbContextOptionsBuilder> setup,
46: IEnumerable<KeyValuePair<string, string>> settings = null)
47: {
48: builder.Add(new DbConfigurationProvider(setup, settings));
49: return builder;
50: }
51: }
ASP.NET Core的配置(1):讀取配置信息
ASP.NET Core的配置(2):配置模型詳解
ASP.NET Core的配置(3): 將配置綁定為對象[上篇]
ASP.NET Core的配置(3): 將配置綁定為對象[下篇]
ASP.NET Core的配置(4):多樣性的配置源[上篇]
ASP.NET Core的配置(4):多樣性的配置源[中篇]
ASP.NET Core的配置(4):多樣性的配置源[下篇]
ASP.NET Core的配置(5):配置的同步[上篇]
ASP.NET Core的配置(5):配置的同步[下篇]
文章列表