4.2 multi-level configuration (lower) and 4.2 configuration change

Source: Internet
Author: User

4.2 multi-level configuration (lower) and 4.2 configuration change

We have implemented the Json configuration source method and registered and used our configuration source in Startup. Next we will focus on how to configure the database. The object class and DbContext code corresponding to the data table are as follows :)

 1     public class ConfigurationSectionInfo 2     { 3         public string AppCode { get; set; } 4         public string SectionCode { get; set; } 5         public string SectionName { get; set; } 6         public string SectionString { get; set; } 7     } 8  9     public class ConfigurationContext : DbContext10     {11         public ConfigurationContext(DbContextOptions options) : base(options)12         {13         }14 15         public DbSet<ConfigurationSectionInfo> ConfigurationSections { get; set; }16 17         protected override void OnModelCreating(ModelBuilder modelBuilder)18         {19             EntityTypeBuilder<ConfigurationSectionInfo> builder = modelBuilder.Entity<ConfigurationSectionInfo>();20 21             builder.ToTable("CONFIGURATION_SECTION_INFO");22             builder.Property(c => c.AppCode).HasColumnName("APP_CODE").IsRequired();23             builder.Property(c => c.SectionCode).HasColumnName("SECTION_CODE").IsRequired();24             builder.Property(c => c.SectionName).HasColumnName("SECTION_NAME").IsRequired();25             builder.Property(c => c.SectionString).HasColumnName("SECTION_STRING").IsRequired();26 27             builder.HasKey(c => new { c.AppCode, c.SectionCode });28         }29     }

The next step is the database configuration source class DatabaseConfigSource, which inherits our own base class ConfigSource and implements the GetConfigurationRoot method.

1 [TypeName ("Database", "Database Configuration")] 2 public class DatabaseConfigSource: ConfigSource 3 {4 public DatabaseConfigSource (string parameter): base (parameter) 5 {6} 7 8 public override IConfigurationRoot GetConfigurationRoot () 9 {10 AppConfigInfo config = AppConfigInfo. getConfig (); 11 12 ConfigurationBuilder builder = new ConfigurationBuilder (); 13 builder. add (new DbConfigurationSource (options => options. useSqlServer (_ Parameter), config. appCode); 14 15 return builder. build (); 16} 17}

Note the AppConfigInfo class, which uses the AppCode attribute and AppCode refers to the application code. Because our public configuration can be used by multiple applications, the AppCode must be passed in when obtaining the configuration in the database mode. It means to obtain the configuration items related to the application (AppCode. Because the configuration data table may contain many application configuration information, we only obtain the configuration information of the current application. The Parameter is a database link string, which can be clearly seen in the introduction of the ConfigSource class in the previous section.

Create ConfigurationBuilder and add DbConfigurationSource, the database implementation of IConfigurationSource. Its core is DbConfigurationProvider. The implementation of DbConfigurationSource and DbConfigurationProvider is as follows:

 1     public class DbConfigurationSource : IConfigurationSource 2     { 3         private readonly Action<DbContextOptionsBuilder> _optionsAction; 4         private readonly string appCode; 5  6         public DbConfigurationSource(Action<DbContextOptionsBuilder> optionsAction, string appCode) 7         { 8             _optionsAction = optionsAction; 9             this.appCode = appCode;10         }11 12         public IConfigurationProvider Build(IConfigurationBuilder builder)13         {14             return new DbConfigurationProvider(_optionsAction, appCode);15         }16     }17 18     public class DbConfigurationProvider : ConfigurationProvider19     {20         private Action<DbContextOptionsBuilder> optionsAction;21         private string appCode;22 23         public DbConfigurationProvider(Action<DbContextOptionsBuilder> optionsAction, string appCode)24         {25             this.optionsAction = optionsAction;26             this.appCode = appCode;27         }28 29         public override void Load()30         {31             var builder = new DbContextOptionsBuilder<ConfigurationContext>();32             optionsAction(builder);33 34             using (var dbContext = new ConfigurationContext(builder.Options))35             {36                 dbContext.Database.EnsureCreated();37                 Data = GetConfigData(dbContext);38             }39         }40 41         private IDictionary<string, string> GetConfigData(ConfigurationContext dbContext)42         {43             List<string> configSections = new List<string>();44 45             var appConfigs = dbContext.ConfigurationSections.Where(a => a.AppCode == this.appCode);46             foreach (ConfigurationSectionInfo info in appConfigs)47             {48                 configSections.Add("\"" + info.SectionCode + "\":{" + info.SectionString + "}");49             }50 51             var defConfigs = dbContext.ConfigurationSections.Where(d => string.IsNullOrEmpty(d.AppCode) && appConfigs.Any(a => a.SectionCode == d.SectionCode));52             foreach (ConfigurationSectionInfo info in defConfigs)53             {54                 configSections.Add("\"" + info.SectionCode + "\":{" + info.SectionString + "}");55             }56 57             string configs = "{\"MicroStrutLibrary\":{" + string.Join(",", configSections) + "}}";58 59             return JsonConfigurationParser.Parse(configs);60         }61     }

The general process of the DbConfigurationProvider program is to read configuration sections related to the current application (AppCode) from the database, and then read the configuration sections with all applications empty (default configuration section ), then all the configuration sections are merged into a total configuration string, and the parsing method is called to generate the configured Key/Value. Resolved code:

1 public static class JsonConfigurationParser 2 {3 private static IDictionary <string, string> _ data; 4 private static Stack <string> _ context; 5 private static string _ currentPath; 6 7 static JsonConfigurationParser () 8 {9 _ data = new SortedDictionary <string, string> (StringComparer. ordinalIgnoreCase); 10 _ context = new Stack <string> (); 11} 12 13 public static IDictionary <string, string> Parse (string Configs) 14 {15 _ data. clear (); 16 17 var jsonConfig = JObject. parse (configs); 18 19 VisitJObject (jsonConfig); 20 21 return _ data; 22} 23 24 private static void VisitJObject (JObject jObject) 25 {26 foreach (var property in jObject. properties () 27 {28 EnterContext (property. name); 29 VisitProperty (property); 30 ExitContext (); 31} 32} 33 34 private static void VisitProperty (JProperty property) 35 {36 VisitToke N (property. value); 37} 38 39 private static void VisitToken (JToken token) 40 {41 switch (token. type) 42 {43 case JTokenType. object: 44 VisitJObject (token. value <JObject> (); 45 break; 46 47 case JTokenType. array: 48 VisitArray (token. value <JArray> (); 49 break; 50 51 case JTokenType. integer: 52 case JTokenType. float: 53 case JTokenType. string: 54 case JTokenType. boolean: 55 case JTokenType. bytes: 56 case JTokenTy Pe. raw: 57 case JTokenType. null: 58 VisitPrimitive (token); 59 break; 60 default: 61 MicroStrutLibraryExceptionHelper. throw (typeof (JsonConfigurationParser ). fullName, LogLevel. error, "incorrect type! "); 62 break; 63} 64} 65 66 private static void VisitArray (JArray array) 67 {68 for (int index = 0; index <array. count; index ++) 69 {70 EnterContext (index. toString (); 71 VisitToken (array [index]); 72 ExitContext (); 73} 74} 75 76 private static void VisitPrimitive (JToken data) 77 {78 var key = _ currentPath; 79 80 MicroStrutLibraryExceptionHelper. trueThrow (_ data. containsKey (key), typeof (JsonConfigurationParser ). fullName, LogLevel. error, $ "duplicate key value {key}"); 81 82 _ data [key] = data. toString (); 83} 84 85 private static void EnterContext (string context) 86 {87 _ context. push (context); 88 _ currentPath = ConfigurationPath. combine (_ context. reverse (); 89} 90 91 private static void ExitContext () 92 {93 _ context. pop (); 94 _ currentPath = ConfigurationPath. combine (_ context. reverse (); 95} 96}

The parsing class code is basically copied from the source code of. net core.

 

Cloud-oriented. net core development framework directory

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.