using System; using System.Collections.Generic; using Microsoft.AnalysisServices.Tabular; using System.Diagnostics; namespace AsPartitionProcessing.SampleClient { #region enum ExecutionMode /// /// Execution mode of the SampleClient application. /// enum ExecutionMode { /// /// Initialize configuration inline using sample values. /// InitializeInline, /// /// Initialize from configuration and logging database. /// InitializeFromDatabase, /// /// Merge partitions in a table based on other parameters. /// MergePartitions, /// /// Defragment partitioned tables in the model. List of partitioned tables defined in the configuration and logging database. /// DefragPartitionedTables } #endregion class Program { //Set sample execution mode here: private static ExecutionMode _executionMode = ExecutionMode.InitializeInline; private static string _modelConfigurationIDs; static int Main(string[] args) { try { #region Set defaults for merging & read command-line arguments if provided string mergeTable = "Internet Sales"; Granularity mergeTargetGranuarity = Granularity.Yearly; string mergePartitionKey = "2012"; bool help; ParseArgs(args, ref mergeTable, ref mergeTargetGranuarity, ref mergePartitionKey, out help); if (help) return 0; //ERROR_SUCCESS #endregion if (_executionMode == ExecutionMode.InitializeInline) { //Perform Processing PartitionProcessor.PerformProcessing(InitializeInline(), LogMessage); } else { List modelsConfig = InitializeFromDatabase(); foreach (ModelConfiguration modelConfig in modelsConfig) { SetCredentials(modelConfig); //For Azure AS switch (_executionMode) { case ExecutionMode.InitializeFromDatabase: //Perform Processing PartitionProcessor.PerformProcessing(modelConfig, LogMessage); break; case ExecutionMode.MergePartitions: //Perform Merging PartitionProcessor.MergePartitions(modelConfig, LogMessage, mergeTable, mergeTargetGranuarity, mergePartitionKey); break; case ExecutionMode.DefragPartitionedTables: //Perform Defrag PartitionProcessor.DefragPartitionedTables(modelConfig, LogMessage); break; default: break; } } } } catch (Exception exc) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(); Console.WriteLine(exc.Message); Console.WriteLine(); Console.ForegroundColor = ConsoleColor.White; if (exc is ArgumentException) { return 160; //ERROR_BAD_ARGUMENTS } else { return 1360; //ERROR_GENERIC_NOT_MAPPED } } finally { if (Debugger.IsAttached) { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("Press any key to exit."); Console.ReadKey(); } } return 0; //ERROR_SUCCESS } private static ModelConfiguration InitializeInline() { ModelConfiguration partitionedModel = new ModelConfiguration( modelConfigurationID: 1, analysisServicesServer: "localhost", analysisServicesDatabase: "AdventureWorks", initialSetUp: true, incrementalOnline: true, integratedAuth: true, userName: "", password: "", maxParallelism: -1, commitTimeout: -1, retryAttempts: 0, retryWaitTimeSeconds: 0, tableConfigurations: new List { new TableConfiguration( tableConfigurationID: 1, analysisServicesTable: "Internet Sales", partitioningConfigurations: new List { new PartitioningConfiguration( partitioningConfigurationID: 1, granularity: Granularity.Monthly, numberOfPartitionsFull: 12, numberOfPartitionsForIncrementalProcess: 3, maxDateIsNow: false, maxDate: Convert.ToDateTime("2012-12-01"), integerDateKey: true, templateSourceQuery: "let\n" + " Source = #\"AdventureWorks\",\n" + " dbo_FactInternetSales = Source{[Schema=\"dbo\",Item=\"FactInternetSales\"]}[Data],\n" + " #\"Filtered Rows\" = Table.SelectRows(dbo_FactInternetSales, each [OrderDateKey] >= {0} and [OrderDateKey] < {1}),\n" + " #\"Sorted Rows\" = Table.Sort(#\"Filtered Rows\",{{\"OrderDateKey\", Order.Ascending}})\n" + "in\n" + " #\"Sorted Rows\"\n" ) } ), new TableConfiguration( tableConfigurationID: 2, analysisServicesTable: "Reseller Sales", partitioningConfigurations: new List { new PartitioningConfiguration( partitioningConfigurationID: 2, granularity: Granularity.Yearly, numberOfPartitionsFull: 3, numberOfPartitionsForIncrementalProcess: 1, maxDateIsNow: false, maxDate: Convert.ToDateTime("2012-12-01"), integerDateKey: false, templateSourceQuery: "let\n" + " Source = #\"AdventureWorks\",\n" + " dbo_FactResellerSales = Source{[Schema=\"dbo\",Item=\"FactResellerSales\"]}[Data],\n" + " #\"Filtered Rows\" = Table.SelectRows(dbo_FactResellerSales, each [OrderDate] >= {0} and [OrderDate] < {1}),\n" + " #\"Sorted Rows\" = Table.Sort(#\"Filtered Rows\",{{\"OrderDate\", Order.Ascending}})\n" + "in\n" + " #\"Sorted Rows\"\n" ) } ) } ); return partitionedModel; } private static List InitializeFromDatabase() { ConfigDatabaseConnectionInfo connectionInfo = new ConfigDatabaseConnectionInfo(); connectionInfo.Server = Settings.Default.ConfigServer; connectionInfo.Database = Settings.Default.ConfigDatabase; connectionInfo.IntegratedAuth = Settings.Default.ConfigDatabaseIntegratedAuth; if (!Settings.Default.ConfigDatabaseIntegratedAuth) { Console.Write("User name for config database: "); connectionInfo.UserName = Console.ReadLine(); Console.Write("Password for config database: "); connectionInfo.Password = ReadPassword(); } return ConfigDatabaseHelper.ReadConfig(connectionInfo, _modelConfigurationIDs); } private static void ParseArgs(string[] args, ref string mergeTable, ref Granularity mergeTargetGranuarity, ref string mergePartitionKey, out bool help) { help = false; if (args.Length > 0) { ArgumentOptions options = new ArgumentOptions(); if (CommandLine.Parser.Default.ParseArguments(args, options)) { if (!String.IsNullOrEmpty(options.ModelConfigurationIDs)) { Console.WriteLine($"ModelConfigurationIDs: {options.ModelConfigurationIDs}"); _modelConfigurationIDs = options.ModelConfigurationIDs; } Console.WriteLine($"Argument ExecutionMode: {options.ExecutionMode}"); switch (options.ExecutionMode) { case "InitializeInline": _executionMode = ExecutionMode.InitializeInline; break; case "InitializeFromDatabase": _executionMode = ExecutionMode.InitializeFromDatabase; break; case "MergePartitions": _executionMode = ExecutionMode.MergePartitions; if (options.MergeTable == null || options.TargetGranularity == null || options.MergePartitionKey == null) { throw new ArgumentException($"ExecutionMode MergePartitions additional arguments not provided or not recognized. Requires --MergeTable, --TargetGranularity, --MergePartitionKey."); } Console.WriteLine($"Argument MergeTable: {options.MergeTable}"); Console.WriteLine($"Argument TargetGranularity: {options.TargetGranularity}"); Console.WriteLine($"Argument MergePartitionKey: {options.MergePartitionKey}"); mergeTable = options.MergeTable; mergeTargetGranuarity = options.TargetGranularity == "Yearly" ? Granularity.Yearly : Granularity.Monthly; mergePartitionKey = options.MergePartitionKey; break; case "DefragPartitionedTables": _executionMode = ExecutionMode.DefragPartitionedTables; break; default: throw new ArgumentException($"Argument --ExecutionMode {options.ExecutionMode} not recognized."); //break; } } else { if (args[0].ToLower() != "--help") { throw new ArgumentException($"Arguments provided not recognized."); } help = true; } } } private static void LogMessage(string message, MessageType messageType, ModelConfiguration partitionedModel) { //Can provide custom logger here try { if (!(_executionMode == ExecutionMode.InitializeInline)) { ConfigDatabaseHelper.LogMessage(message, messageType, partitionedModel); } Console.WriteLine(message); } catch (Exception exc) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(exc.Message); Console.WriteLine(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("Press any key to exit."); Console.ReadKey(); Console.ForegroundColor = ConsoleColor.White; Environment.Exit(0); //Avoid recursion if errored connecting to db } } private static void SetCredentials(ModelConfiguration modelConfig) { if (!modelConfig.IntegratedAuth) //For Azure AS { Console.WriteLine(); Console.Write("User name for AS server: "); modelConfig.UserName = Console.ReadLine(); Console.Write("Password for AS server: "); modelConfig.Password = ReadPassword(); } } private static string ReadPassword() { string password = ""; ConsoleKeyInfo info = Console.ReadKey(true); while (info.Key != ConsoleKey.Enter) { if (info.Key != ConsoleKey.Backspace) { Console.Write("*"); password += info.KeyChar; } else if (info.Key == ConsoleKey.Backspace) { if (!string.IsNullOrEmpty(password)) { // remove one character from the list of password characters password = password.Substring(0, password.Length - 1); // get the location of the cursor int pos = Console.CursorLeft; // move the cursor to the left by one character Console.SetCursorPosition(pos - 1, Console.CursorTop); // replace it with space Console.Write(" "); // move the cursor to the left by one character again Console.SetCursorPosition(pos - 1, Console.CursorTop); } } info = Console.ReadKey(true); } // add a new line because user pressed enter at the end of password Console.WriteLine(); return password; } } }