/// <summary> /// Generates *CREATE MASTER KEY* statements /// </summary> /// <param name="configFile"></param> public static void CreateExternalDataSource(Configs.CreateExternalDataSource[] config) { // load data Configs.CreateExternalDataSource sharedConfig = new Configs.CreateExternalDataSource(); string templateContents = Generators.GetTemplateContents("CreateExternalDataSource.txt"); // generate output one file at a time for (int i = 0; i < config.Length; i++) { // merge with the previous full version of the config sharedConfig = (Configs.CreateExternalDataSource)config[i].Merge(sharedConfig).Clone(); // there may be 2 loops if it generates scripts for mutual access for (int j = 0; j < 2; j++) { // interpolate string outputContents = string.Format(templateContents, config[i].localDB, config[i].externalDB, config[i].serverName, config[i].credential); string outputFileName = $"CreateExternalDataSource__{config[i].localDB}__{config[i].externalDB}__x{fileExtSQL}"; Generators.SaveGeneratedScript(outputContents, outputFileName, i); // exit the loop now if the data source is not reciprocal - one way only if (config[i].twoway != "1" || j == 1) { break; } // or swap the DBs if it's two-way generation string ldb = config[i].localDB; config[i].localDB = config[i].externalDB; config[i].externalDB = ldb; } } }
/// <summary> /// Genrate a generic list of tables as JSON for further editing. /// </summary> /// <param name="configFile"></param> public static void GenerateSecondaryConfigFiles(Configs.InitialConfig config) { // output collections per config file List <Configs.AllTables> tableListMirror = new List <Configs.AllTables>(); // config for mirror tables List <Configs.AllTables> tableListRO = new List <Configs.AllTables>(); // config for read-only external tables List <Configs.AllTables> spList = new List <Configs.AllTables>(); // config for remote SP proxies List <Configs.CreateMasterKey> masterKeyList = new List <Configs.CreateMasterKey>(); // config for Master Key config List <Configs.CreateExternalDataSource> extDataSrcList = new List <Configs.CreateExternalDataSource>(); // config for ext data source config Configs.AllTables prevTable = new Configs.AllTables(); // a container for tracking changes // normalise line endings and remove [ ] config.masterTables ??= ""; config.masterTablesRO ??= ""; config.masterTables = config.masterTables.Replace("\r", "").Replace("[", "").Replace("]", "").Replace(" ", ""); config.masterTablesRO = config.masterTablesRO.Replace("\r", "").Replace("[", "").Replace("]", "").Replace(" ", ""); config.connections = config.connections.Replace("\r", ""); var jsonSettings = new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore }; // ignore null properties // combine mirror and ro lists string[] allTables = config.masterTables.Split("\n"); string[] roTables = config.masterTablesRO.Split("\n"); int mirrorCount = allTables.Length; if (roTables.Length > 0) { Array.Resize <string>(ref allTables, mirrorCount + roTables.Length); Array.Copy(roTables, 0, allTables, mirrorCount, roTables.Length); } foreach (string tableLine in allTables) { mirrorCount--; // decrement the counter to know when mirrors turn into read-only tables if (mirrorCount == -1) { prevTable = new Configs.AllTables(); // reset on switching from mirrors to ROs } // get the 3-part name like DB_STATS..TB_MANUALRESERVATION if (string.IsNullOrWhiteSpace(tableLine)) { continue; // skip empty lines } string[] tableParts = tableLine.Trim().Split("."); // check the format if (tableParts.Length != 3) { throw new Exception($"Must be a 3-part name: {tableLine}"); } if (tableParts[0].ToLower() == config.mirrorDB.ToLower()) { throw new Exception($"Found a self-reference: {tableLine}"); } // add mirror table details var tableItem = new Configs.AllTables() { masterTableOrSP = tableParts[2], masterDB = (prevTable.masterDB?.ToLower() != tableParts[0].ToLower()) ? tableParts[0] : null, mirrorDB = (prevTable.mirrorDB?.ToLower() != config.mirrorDB.ToLower()) ? config.mirrorDB : null, masterCS = (prevTable.masterDB?.ToLower() != tableParts[0].ToLower()) ? DbAccess.GetConnectionString(config, tableParts[0]) : null }; if (mirrorCount >= 0) { tableListMirror.Add(tableItem); // add to mirror collection } else { tableListRO.Add(tableItem); // add to read-only collection } prevTable.Merge(tableItem, true); // merge with overwrite // process MasterKeyConfig var masterKeyItem = new Configs.CreateMasterKey(); if (masterKeyList.Count == 0) // add full details to the first item only { masterKeyItem.password = config.password; masterKeyItem.credential = config.credential; masterKeyItem.identity = config.identity; masterKeyItem.secret = config.secret; // the very first record is actually for the mirror DB, so we have to re-initialise // not to miss the first master table from the loop masterKeyItem.localDB = config.mirrorDB; masterKeyList.Add(masterKeyItem); masterKeyItem = new Configs.CreateMasterKey(); } if (!string.IsNullOrEmpty(tableItem.masterDB)) { masterKeyItem.localDB = tableItem.masterDB; // only local db can be added automatically masterKeyList.Add(masterKeyItem); } // process ExternalDataSource config var extDataSrcItem = new Configs.CreateExternalDataSource(); if (extDataSrcList.Count == 0) // add full details to the first item only { extDataSrcItem.serverName = config.serverName; extDataSrcItem.credential = config.credential; extDataSrcItem.twoway = config.twoway; extDataSrcItem.externalDB = config.mirrorDB; } if (!string.IsNullOrEmpty(tableItem.masterDB)) { extDataSrcItem.localDB = tableItem.masterDB; // only local db can be added automatically extDataSrcList.Add(extDataSrcItem); } // check if the table exists in Master DB string tableCols = DbAccess.GetTableColumns(prevTable.masterCS, prevTable.masterTableOrSP); if (string.IsNullOrEmpty(tableCols)) { Program.WriteLine(); Program.WriteLine($"Missing table definition for {prevTable.masterDB}..{prevTable.masterTableOrSP}", ConsoleColor.Red); Program.ExitApp(); } } // process the list of SPs prevTable = new Configs.AllTables(); // restart the properties inheritance string[] masterSPs = (config.masterSPs ?? "").Split("\n"); foreach (string spLine in masterSPs) { // get the 3-part name like DB_STATS..TB_MANUALRESERVATION if (string.IsNullOrWhiteSpace(spLine)) { continue; // skip empty lines } string[] spParts = spLine.Trim().Split("."); // check the format if (spParts.Length != 3) { throw new Exception($"Must be a 3-part name: {spLine}"); } if (spParts[0].ToLower() == config.mirrorDB.ToLower()) { throw new Exception($"Found a self-reference: {spLine}"); } // add mirror table details var spItem = new Configs.AllTables() { masterTableOrSP = spParts[2], masterDB = (prevTable.masterDB?.ToLower() != spParts[0].ToLower()) ? spParts[0] : null, mirrorDB = (prevTable.mirrorDB?.ToLower() != config.mirrorDB.ToLower()) ? config.mirrorDB : null, masterCS = (prevTable.masterDB?.ToLower() != spParts[0].ToLower()) ? DbAccess.GetConnectionString(config, spParts[0]) : null }; spList.Add(spItem); // add to mirror collection prevTable.Merge(spItem, true); // merge with overwrite // process MasterKeyConfig var masterKeyItem = new Configs.CreateMasterKey(); if (masterKeyList.Count == 0) // add full details to the first item only { masterKeyItem.password = config.password; masterKeyItem.credential = config.credential; masterKeyItem.identity = config.identity; masterKeyItem.secret = config.secret; // the very first record is actually for the mirror DB, so we have to re-initialise // not to miss the first master table from the loop masterKeyItem.localDB = config.mirrorDB; masterKeyList.Add(masterKeyItem); } // process ExternalDataSource config var extDataSrcItem = new Configs.CreateExternalDataSource(); if (spList.Count == 1) // add full details to the first item only { extDataSrcItem.serverName = config.serverName; extDataSrcItem.credential = config.credential; extDataSrcItem.localDB = config.mirrorDB; } extDataSrcItem.externalDB = spItem.masterDB; extDataSrcList.Add(extDataSrcItem); // check if the SP exists in Master DB if (!DbAccess.CheckProcedureExists(prevTable.masterCS, prevTable.masterTableOrSP)) { Program.WriteLine(); Program.WriteLine($"Missing SP definition for {prevTable.masterDB}..{prevTable.masterTableOrSP}", ConsoleColor.Red); Program.ExitApp(); } } // save as files if (tableListMirror.Count > 0) { Configs.GenericConfigEntry.SaveConfigFile(Program.FileNames.TablesConfigMirror, JsonConvert.SerializeObject(tableListMirror.ToArray(), jsonSettings)); } if (tableListRO.Count > 0) { Configs.GenericConfigEntry.SaveConfigFile(Program.FileNames.TablesConfigReadOnly, JsonConvert.SerializeObject(tableListRO.ToArray(), jsonSettings)); } if (spList.Count > 0) { Configs.GenericConfigEntry.SaveConfigFile(Program.FileNames.SPsConfig, JsonConvert.SerializeObject(spList.ToArray(), jsonSettings)); } Configs.GenericConfigEntry.SaveConfigFile(Program.FileNames.MasterKeyConfig, JsonConvert.SerializeObject(masterKeyList.ToArray(), jsonSettings)); Configs.GenericConfigEntry.SaveConfigFile(Program.FileNames.ExternalDataSourceConfig, JsonConvert.SerializeObject(extDataSrcList.ToArray(), jsonSettings)); }