361 lines
15 KiB
C#
361 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Microsoft.AnalysisServices.Tabular;
|
|
using System.Diagnostics;
|
|
|
|
namespace AsPartitionProcessing.SampleClient
|
|
{
|
|
#region enum ExecutionMode
|
|
|
|
/// <summary>
|
|
/// Execution mode of the SampleClient application.
|
|
/// </summary>
|
|
enum ExecutionMode
|
|
{
|
|
/// <summary>
|
|
/// Initialize configuration inline using sample values.
|
|
/// </summary>
|
|
InitializeInline,
|
|
|
|
/// <summary>
|
|
/// Initialize from configuration and logging database.
|
|
/// </summary>
|
|
InitializeFromDatabase,
|
|
|
|
/// <summary>
|
|
/// Merge partitions in a table based on other parameters.
|
|
/// </summary>
|
|
MergePartitions,
|
|
|
|
/// <summary>
|
|
/// Defragment partitioned tables in the model. List of partitioned tables defined in the configuration and logging database.
|
|
/// </summary>
|
|
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<ModelConfiguration> 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,
|
|
tableConfigurations:
|
|
new List<TableConfiguration>
|
|
{
|
|
new TableConfiguration(
|
|
tableConfigurationID: 1,
|
|
analysisServicesTable: "Internet Sales",
|
|
partitioningConfigurations:
|
|
new List<PartitioningConfiguration>
|
|
{
|
|
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<PartitioningConfiguration>
|
|
{
|
|
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<ModelConfiguration> 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, ModelConfiguration partitionedModel)
|
|
{
|
|
//Can provide custom logger here
|
|
|
|
try
|
|
{
|
|
if (!(_executionMode == ExecutionMode.InitializeInline))
|
|
{
|
|
ConfigDatabaseHelper.LogMessage(message, 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;
|
|
}
|
|
|
|
}
|
|
}
|
|
|