SetUpAggs
This commit is contained in:
parent
198abe4ab6
commit
94a22ea210
45
SetUpAggs/AW Internet Sales/AdventureWorksAggs.smproj
Normal file
45
SetUpAggs/AW Internet Sales/AdventureWorksAggs.smproj
Normal file
@ -0,0 +1,45 @@
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Development</Configuration>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{8CE414BB-95B2-4C99-9E03-51BA72086E22}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>MyRootNamespace</RootNamespace>
|
||||
<AssemblyName>MyAssemblyName</AssemblyName>
|
||||
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<Name>AdventureWorksAggs</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Development' ">
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DeploymentServerName>asazure://southcentralus.asazure.windows.net/chwade003</DeploymentServerName>
|
||||
<DeploymentServerEdition>Developer</DeploymentServerEdition>
|
||||
<DeploymentServerVersion>Unknown</DeploymentServerVersion>
|
||||
<DeploymentServerDatabase>AdventureWorksAg</DeploymentServerDatabase>
|
||||
<DeploymentServerCubeName>Model</DeploymentServerCubeName>
|
||||
<DeploymentOptionProcessing>Default</DeploymentOptionProcessing>
|
||||
<DeploymentOptionTransactionalDeployment>False</DeploymentOptionTransactionalDeployment>
|
||||
<DeploymentOptionDirectQueryMode>InMemory</DeploymentOptionDirectQueryMode>
|
||||
<DeploymentOptionQueryImpersonation>Default</DeploymentOptionQueryImpersonation>
|
||||
<DeploymentOptionADALCache>Default</DeploymentOptionADALCache>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == '' ">
|
||||
<DeploymentServerName>asazure://aspaastest14.asazure-int.windows.net/sukanyasaltsrc1</DeploymentServerName>
|
||||
<DeploymentServerEdition>Developer</DeploymentServerEdition>
|
||||
<DeploymentServerVersion>Unknown</DeploymentServerVersion>
|
||||
<DeploymentServerDatabase>AdventureWorksAggs</DeploymentServerDatabase>
|
||||
<DeploymentServerCubeName>Model</DeploymentServerCubeName>
|
||||
<DeploymentOptionProcessing>Default</DeploymentOptionProcessing>
|
||||
<DeploymentOptionTransactionalDeployment>False</DeploymentOptionTransactionalDeployment>
|
||||
<DeploymentOptionDirectQueryMode>InMemory</DeploymentOptionDirectQueryMode>
|
||||
<DeploymentOptionQueryImpersonation>Default</DeploymentOptionQueryImpersonation>
|
||||
<DeploymentOptionADALCache>Default</DeploymentOptionADALCache>
|
||||
</PropertyGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Compile Include="Model.bim">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Business Intelligence Semantic Model\1.0\Microsoft.AnalysisServices.VSHostBuilder.targets" />
|
||||
</Project>
|
1626
SetUpAggs/AW Internet Sales/Model.bim
Normal file
1626
SetUpAggs/AW Internet Sales/Model.bim
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Development</Configuration>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{274b7b29-6eae-44ce-a06b-ed91f1e52734}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>MyRootNamespace</RootNamespace>
|
||||
<AssemblyName>MyAssemblyName</AssemblyName>
|
||||
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<Name>AdventureWorksAggsProvider</Name>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Development' ">
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DeploymentServerName>asazure://southcentralus.asazure.windows.net/chwade003</DeploymentServerName>
|
||||
<DeploymentServerEdition>Developer</DeploymentServerEdition>
|
||||
<DeploymentServerVersion>Unknown</DeploymentServerVersion>
|
||||
<DeploymentServerDatabase>AdventureWorksAggsProvider_PH</DeploymentServerDatabase>
|
||||
<DeploymentServerCubeName>Model</DeploymentServerCubeName>
|
||||
<DeploymentOptionProcessing>Default</DeploymentOptionProcessing>
|
||||
<DeploymentOptionTransactionalDeployment>False</DeploymentOptionTransactionalDeployment>
|
||||
<DeploymentOptionADALCache>Default</DeploymentOptionADALCache>
|
||||
<DeploymentOptionDirectQueryMode>InMemory</DeploymentOptionDirectQueryMode>
|
||||
<DeploymentOptionQueryImpersonation>Default</DeploymentOptionQueryImpersonation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == '' ">
|
||||
<DeploymentServerName>asazure://aspaastest14.asazure-int.windows.net/sukanyasaltsrc1</DeploymentServerName>
|
||||
<DeploymentServerEdition>Developer</DeploymentServerEdition>
|
||||
<DeploymentServerVersion>Unknown</DeploymentServerVersion>
|
||||
<DeploymentServerDatabase>AdventureWorksAggsProvider</DeploymentServerDatabase>
|
||||
<DeploymentServerCubeName>Model</DeploymentServerCubeName>
|
||||
<DeploymentOptionProcessing>Default</DeploymentOptionProcessing>
|
||||
<DeploymentOptionTransactionalDeployment>False</DeploymentOptionTransactionalDeployment>
|
||||
<DeploymentOptionADALCache>Default</DeploymentOptionADALCache>
|
||||
<DeploymentOptionDirectQueryMode>InMemory</DeploymentOptionDirectQueryMode>
|
||||
<DeploymentOptionQueryImpersonation>Default</DeploymentOptionQueryImpersonation>
|
||||
</PropertyGroup>
|
||||
<ItemGroup />
|
||||
<ItemGroup>
|
||||
<Compile Include="Model.bim">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Business Intelligence Semantic Model\1.0\Microsoft.AnalysisServices.VSHostBuilder.targets" />
|
||||
</Project>
|
1263
SetUpAggs/AdventureWorksAggsProvider/Model.bim
Normal file
1263
SetUpAggs/AdventureWorksAggsProvider/Model.bim
Normal file
File diff suppressed because it is too large
Load Diff
74
SetUpAggs/AggsConfig.json
Normal file
74
SetUpAggs/AggsConfig.json
Normal file
@ -0,0 +1,74 @@
|
||||
{
|
||||
"database": {
|
||||
"name": "AdventureWorksAggsProvider_PH",
|
||||
"tables": [
|
||||
{
|
||||
"name": "DimGeography",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "DimCustomer",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "DimDate",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "DimProductSubcategory",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "DimProductCategory",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "FactInternetSalesAgg",
|
||||
"mode": "Import",
|
||||
"aggregationRules": [
|
||||
{
|
||||
"aggTableColumn": "OrderDateKey",
|
||||
"summarization": "GroupBy",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "OrderDateKey"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "CustomerKey",
|
||||
"summarization": "GroupBy",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "CustomerKey"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "ProductSubcategoryKey",
|
||||
"summarization": "GroupBy",
|
||||
"detailTable": "DimProduct",
|
||||
"detailTableColumn": "ProductSubcategoryKey"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "SalesAmount_Sum",
|
||||
"summarization": "Sum",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "SalesAmount"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "UnitPrice_Sum",
|
||||
"summarization": "Min",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "UnitPrice"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "UnitPrice_Count",
|
||||
"summarization": "Count",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "UnitPrice"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "FactInternetSales_Count",
|
||||
"summarization": "CountTableRows",
|
||||
"detailTable": "FactInternetSales"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
74
SetUpAggs/AggsConfig2.json
Normal file
74
SetUpAggs/AggsConfig2.json
Normal file
@ -0,0 +1,74 @@
|
||||
{
|
||||
"database": {
|
||||
"name": "AdventureWorksAggsProvider_PH",
|
||||
"tables": [
|
||||
{
|
||||
"name": "DimGeography",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "DimCustomer",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "DimDate",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "DimProductSubcategory",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "DimProductCategory",
|
||||
"mode": "Dual"
|
||||
},
|
||||
{
|
||||
"name": "FactInternetSalesAgg",
|
||||
"mode": "Import",
|
||||
"aggregationRules": [
|
||||
{
|
||||
"aggTableColumn": "OrderDateKey",
|
||||
"summarization": "GroupBy",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "OrderDateKey"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "CustomerKey",
|
||||
"summarization": "GroupBy",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "CustomerKey"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "ProductSubcategoryKey",
|
||||
"summarization": "GroupBy",
|
||||
"detailTable": "DimProduct",
|
||||
"detailTableColumn": "ProductSubcategoryKey"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "SalesAmount_Sum",
|
||||
"summarization": "Sum",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "SalesAmount"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "UnitPrice_Sum",
|
||||
"summarization": "Sum",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "UnitPrice"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "UnitPrice_Count",
|
||||
"summarization": "Count",
|
||||
"detailTable": "FactInternetSales",
|
||||
"detailTableColumn": "UnitPrice"
|
||||
},
|
||||
{
|
||||
"aggTableColumn": "FactInternetSales_Count",
|
||||
"summarization": "CountTableRows",
|
||||
"detailTable": "FactInternetSales"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
6
SetUpAggs/App.config
Normal file
6
SetUpAggs/App.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
|
||||
</startup>
|
||||
</configuration>
|
463
SetUpAggs/Program.cs
Normal file
463
SetUpAggs/Program.cs
Normal file
@ -0,0 +1,463 @@
|
||||
using Microsoft.AnalysisServices.Tabular;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using PowerArgs;
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace SetUpAggs
|
||||
{
|
||||
#region JsonHelper Class
|
||||
|
||||
public static class JsonHelper
|
||||
{
|
||||
public static string FromClass<T>(T data, bool isEmptyToNull = false,
|
||||
JsonSerializerSettings jsonSettings = null)
|
||||
{
|
||||
string response = string.Empty;
|
||||
|
||||
if (!EqualityComparer<T>.Default.Equals(data, default(T)))
|
||||
response = JsonConvert.SerializeObject(data, jsonSettings);
|
||||
|
||||
return isEmptyToNull ? (response == "{}" ? "null" : response) : response;
|
||||
}
|
||||
|
||||
public static T ToClass<T>(string data, JsonSerializerSettings jsonSettings = null)
|
||||
{
|
||||
var response = default(T);
|
||||
|
||||
if (!string.IsNullOrEmpty(data))
|
||||
response = jsonSettings == null
|
||||
? JsonConvert.DeserializeObject<T>(data)
|
||||
: JsonConvert.DeserializeObject<T>(data, jsonSettings);
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Json Configuration Classes
|
||||
|
||||
public partial class AggsConfiguration
|
||||
{
|
||||
[JsonProperty("database")]
|
||||
public Database Database { get; set; }
|
||||
}
|
||||
|
||||
public partial class Database
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("tables")]
|
||||
public Table[] Tables { get; set; }
|
||||
}
|
||||
|
||||
public partial class Table
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("mode")]
|
||||
public string Mode { get; set; }
|
||||
|
||||
[JsonProperty("aggregationRules", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public AggregationRule[] AggregationRules { get; set; }
|
||||
}
|
||||
|
||||
public partial class AggregationRule
|
||||
{
|
||||
[JsonProperty("aggTableColumn")]
|
||||
public string AggTableColumn { get; set; }
|
||||
|
||||
[JsonProperty("summarization")]
|
||||
public string Summarization { get; set; }
|
||||
|
||||
[JsonProperty("detailTable")]
|
||||
public string DetailTable { get; set; }
|
||||
|
||||
[JsonProperty("detailTableColumn", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string DetailTableColumn { get; set; }
|
||||
}
|
||||
|
||||
public partial class Object
|
||||
{
|
||||
[JsonProperty("database")]
|
||||
public string Database { get; set; }
|
||||
}
|
||||
|
||||
public partial class AggsConfiguration
|
||||
{
|
||||
public static AggsConfiguration FromJson(string json) => JsonConvert.DeserializeObject<AggsConfiguration>(json, SetUpAggs.Converter.Settings);
|
||||
}
|
||||
|
||||
public static class Serialize
|
||||
{
|
||||
public static string ToJson(this AggsConfiguration self) => JsonConvert.SerializeObject(self, SetUpAggs.Converter.Settings);
|
||||
}
|
||||
|
||||
internal static class Converter
|
||||
{
|
||||
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
|
||||
{
|
||||
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
|
||||
DateParseHandling = DateParseHandling.None,
|
||||
Converters =
|
||||
{
|
||||
new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
|
||||
},
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Command Line Utility Arguments Handling
|
||||
|
||||
[ArgExceptionBehavior(ArgExceptionPolicy.StandardExceptionHandling)]
|
||||
public class AggConfigurationUtility
|
||||
{
|
||||
Microsoft.AnalysisServices.Tabular.Server server = new Microsoft.AnalysisServices.Tabular.Server();
|
||||
Microsoft.AnalysisServices.Tabular.Database database = new Microsoft.AnalysisServices.Tabular.Database();
|
||||
AggsConfiguration aggsConfig;
|
||||
|
||||
[HelpHook, ArgShortcut("-?"), ArgDescription("Shows this help")]
|
||||
public bool Help { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Validate the configuration file against the model before applying changes
|
||||
/// </summary>
|
||||
/// <param name="tableConfig"></param>
|
||||
private void ValidateConfigurationOfTable(Table tableConfig)
|
||||
{
|
||||
var table = database.Model.Tables.Find(tableConfig.Name);
|
||||
|
||||
if (table == null)
|
||||
throw new Exception($"Could not find table [{tableConfig.Name}]");
|
||||
|
||||
try
|
||||
{
|
||||
Enum.Parse(typeof(ModeType), tableConfig.Mode);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
throw new Exception($"Table [{tableConfig.Name}] has invalid mode type {tableConfig.Mode}, must be one of Default, DirectQuery, Dual, or Import");
|
||||
}
|
||||
|
||||
if (table.Partitions.Count == 0)
|
||||
throw new Exception($"No partitions found for table [{table.Name}]");
|
||||
|
||||
if(tableConfig.AggregationRules != null)
|
||||
foreach (AggregationRule rule in tableConfig.AggregationRules)
|
||||
{
|
||||
if(rule.Summarization != "CountTableRows")
|
||||
try
|
||||
{
|
||||
Enum.Parse(typeof(SummarizationType), rule.Summarization);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new Exception($"Aggregation rule summarization invalid [{rule.Summarization}], must be one of GroupBy, Sum, Min, Max, Count, or CountTableRows");
|
||||
}
|
||||
|
||||
Microsoft.AnalysisServices.Tabular.Column aggColumn = table.Columns.Find(rule.AggTableColumn);
|
||||
|
||||
if (aggColumn == null)
|
||||
throw new Exception($"Cound not find aggregation column [{table.Name}].[{rule.AggTableColumn}] in model");
|
||||
|
||||
var detailTable = database.Model.Tables.Find(rule.DetailTable);
|
||||
|
||||
if (detailTable == null)
|
||||
throw new Exception($"Cound not find detail table [{rule.DetailTable}] in model");
|
||||
|
||||
var detailColumn = (rule.DetailTableColumn == null ? null : detailTable.Columns.Find(rule.DetailTableColumn));
|
||||
|
||||
bool isCountAggregate = rule.Summarization != "Count" || rule.Summarization != "CountTableRows";
|
||||
|
||||
if (detailColumn == null && !isCountAggregate)
|
||||
throw new Exception($"Cound not find detail column [{rule.DetailTable}].[{rule.DetailTableColumn}] in model");
|
||||
|
||||
if (!isCountAggregate && aggColumn.DataType != detailColumn.DataType)
|
||||
throw new Exception($"Data type mismatch for aggregation column [{table.Name}].[{rule.AggTableColumn}] and detail column [{rule.DetailTable}].[{rule.DetailTableColumn}]");
|
||||
|
||||
}
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine($"Validated aggregation rules for [{table.Name}], mode currently set to {table.Partitions[0].Mode.ToString()}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the differences between the configuration file and the model
|
||||
/// </summary>
|
||||
/// <param name="tableConfig"></param>
|
||||
private int ApplyConfigurationOfTable(Table tableConfig)
|
||||
{
|
||||
// Update mode of each partition of the table if a difference is found between the model and the configuration
|
||||
var table = database.Model.Tables.Find(tableConfig.Name);
|
||||
int partitionModesChanged = 0;
|
||||
table.Partitions.ForEach(p =>
|
||||
{
|
||||
var mode = (ModeType)Enum.Parse(typeof(ModeType), tableConfig.Mode);
|
||||
if (p.Mode != mode)
|
||||
{
|
||||
p.Mode = mode;
|
||||
partitionModesChanged++;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Remove all alternateOf definitions from the model that do not match an aggregation rule in the configuration
|
||||
int alternateOfRemoved = 0;
|
||||
table.Columns.ForEach(c =>
|
||||
{
|
||||
int ruleMatch = 0;
|
||||
|
||||
if(tableConfig.AggregationRules != null && c.AlternateOf != null)
|
||||
ruleMatch = tableConfig.AggregationRules.Where(r =>
|
||||
r.Summarization != "CountTableRows" &&
|
||||
r.AggTableColumn == c.Name &&
|
||||
r.DetailTable == c.AlternateOf.BaseColumn.Table.Name &&
|
||||
r.DetailTableColumn == c.AlternateOf.BaseColumn.Name &&
|
||||
(SummarizationType)Enum.Parse(typeof(SummarizationType), r.Summarization) == c.AlternateOf.Summarization
|
||||
).Count() +
|
||||
tableConfig.AggregationRules.Where(r =>
|
||||
r.Summarization == "CountTableRows" &&
|
||||
r.AggTableColumn == c.Name &&
|
||||
r.DetailTable == c.AlternateOf.BaseTable.Name &&
|
||||
c.AlternateOf.Summarization == SummarizationType.Count
|
||||
).Count();
|
||||
|
||||
if (ruleMatch == 0 && c.AlternateOf != null)
|
||||
{
|
||||
var baseObjectName = c.AlternateOf.BaseColumn == null ?
|
||||
String.Format("[{0}]", c.AlternateOf.BaseTable.Name) :
|
||||
String.Format("[{0}].[{1}]", c.AlternateOf.BaseColumn.Table.Name, c.AlternateOf.BaseColumn.Name);
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine($"Removing aggregation rule from column [{c.Name}] with alternate of {baseObjectName} aggregation {c.AlternateOf.Summarization}");
|
||||
|
||||
c.AlternateOf = null;
|
||||
alternateOfRemoved++;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Add all alternateOf definitions from the configuration that do not match an alternateOf definition in the model
|
||||
int alternateOfAdded = 0;
|
||||
if(tableConfig.AggregationRules != null)
|
||||
tableConfig.AggregationRules.ForEach(r =>
|
||||
{
|
||||
var column = table.Columns.First(c => c.Name == r.AggTableColumn);
|
||||
var detailTable = database.Model.Tables.Find(r.DetailTable);
|
||||
var detailColumn = (r.DetailTableColumn != null) ? detailTable.Columns.Find(r.DetailTableColumn) : null;
|
||||
|
||||
if (column.AlternateOf == null)
|
||||
{
|
||||
if (r.Summarization == "CountTableRows")
|
||||
column.AlternateOf = new AlternateOf
|
||||
{
|
||||
Summarization = SummarizationType.Count,
|
||||
BaseTable = detailTable
|
||||
};
|
||||
else
|
||||
column.AlternateOf = new AlternateOf
|
||||
{
|
||||
Summarization = (SummarizationType)Enum.Parse(typeof(SummarizationType), r.Summarization),
|
||||
BaseColumn = detailColumn
|
||||
};
|
||||
|
||||
alternateOfAdded++;
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine($"Adding aggregation rule for column [{column.Name}] with alternate of [{detailTable.Name + (detailColumn == null ? string.Empty : "].[" + detailColumn.Name)}] aggregation {column.AlternateOf.Summarization}");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return partitionModesChanged + alternateOfRemoved + alternateOfAdded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Connect to analysis services instance and database, throw if error is encountered
|
||||
/// </summary>
|
||||
/// <param name="serverName"></param>
|
||||
private void Connect(string serverName)
|
||||
{
|
||||
//string connectionString = $"Provider=MSOLAP;Data Source={args.Server};";
|
||||
string connectionString = $"Provider=MSOLAP;Data Source={serverName};Integrated Security=SSPI;Persist Security Info=True;";
|
||||
server.Connect(connectionString);
|
||||
|
||||
database = server.Databases.FindByName(aggsConfig.Database.Name);
|
||||
|
||||
if (database == null)
|
||||
{
|
||||
throw new Microsoft.AnalysisServices.ConnectionException($"Could not find database [{aggsConfig.Database.Name}]");
|
||||
}
|
||||
}
|
||||
|
||||
[ArgActionMethod, ArgDescription("Applies the Aggs configuration to the model specified")]
|
||||
public void Apply(ServerAndConfigurationArgs args)
|
||||
{
|
||||
List<Microsoft.AnalysisServices.Tabular.Table> updatedTableCollection = new List<Microsoft.AnalysisServices.Tabular.Table>();
|
||||
|
||||
// Read configuration file
|
||||
aggsConfig = JsonHelper.ToClass<AggsConfiguration>(File.ReadAllText(args.ConfigFile));
|
||||
|
||||
#region Connect
|
||||
|
||||
Connect(args.Server);
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine($"Start: {DateTime.Now.ToString("hh:mm:ss tt")}");
|
||||
Console.WriteLine($"Server: {args.Server}");
|
||||
Console.WriteLine($"Database: {aggsConfig.Database.Name}");
|
||||
|
||||
#endregion
|
||||
|
||||
#region Validate Configuration Against Model
|
||||
|
||||
aggsConfig.Database.Tables.ForEach(x => ValidateConfigurationOfTable(x));
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine($"Validation successful");
|
||||
|
||||
#endregion
|
||||
|
||||
#region Update Model Compatibility
|
||||
|
||||
//Set database compat level
|
||||
if (database.CompatibilityLevel < 1465)
|
||||
{
|
||||
database.CompatibilityLevel = 1465;
|
||||
database.Update();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Apply Model Changes
|
||||
|
||||
var changesApplied = 0;
|
||||
aggsConfig.Database.Tables.ForEach(x =>
|
||||
{
|
||||
|
||||
var delta = ApplyConfigurationOfTable(x);
|
||||
|
||||
if (delta > 0)
|
||||
updatedTableCollection.Add(database.Model.Tables.Find(x.Name));
|
||||
|
||||
changesApplied += delta;
|
||||
}
|
||||
);
|
||||
|
||||
if (changesApplied == 0)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine($"No changes applied to model");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine($"Applied model changes");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Expand Full
|
||||
|
||||
if (changesApplied == 0)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("Skipping write to database, no changes detected");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set database UpdateOptions to ExpandFull
|
||||
try
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.Write("Writing model changes to database ");
|
||||
database.Update(Microsoft.AnalysisServices.UpdateOptions.ExpandFull);
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine("SUCCESS");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine("FAILED");
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Refresh Tables as Required
|
||||
|
||||
if (changesApplied == 0)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("Skipping table refresh, no changes detected");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("Refreshing tables - begin: " + DateTime.Now.ToString("hh:mm:ss tt"));
|
||||
|
||||
foreach (var tableObj in updatedTableCollection)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.Write($"Refreshing table [{tableObj.Name}] ");
|
||||
tableObj.RequestRefresh(RefreshType.Full);
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
Console.WriteLine("COMPLETE");
|
||||
}
|
||||
|
||||
database.Model.SaveChanges();
|
||||
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("Refreshing tables - end: " + DateTime.Now.ToString("hh:mm:ss tt"));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
public class ServerAndConfigurationArgs
|
||||
{
|
||||
[ArgRequired, ArgDescription("The URL to the Azure Analysis Services instance e.g.: asazure://host/instance"), ArgPosition(1)]
|
||||
public string Server { get; set; }
|
||||
|
||||
[ArgRequired, ArgDescription("The file path to the JSON configuration file to apply to the database"), ArgPosition(2)]
|
||||
public string ConfigFile { get; set; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
Args.InvokeAction<AggConfigurationUtility>(args);
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine("");
|
||||
Console.WriteLine($"Exception occurred: {DateTime.Now.ToString("hh:mm:ss tt")}");
|
||||
Console.WriteLine($"Exception message: {exc.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("Press any key to exit");
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
SetUpAggs/Properties/AssemblyInfo.cs
Normal file
36
SetUpAggs/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SetUpAggs")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SetUpAggs")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("2433edbd-ffb1-42b9-a0bf-2dfc2953acf1")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
74
SetUpAggs/SetUpAggs.csproj
Normal file
74
SetUpAggs/SetUpAggs.csproj
Normal file
@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<RootNamespace>SetUpAggs</RootNamespace>
|
||||
<AssemblyName>SetUpAggs</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AnalysisServices, Version=15.8.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.AnalysisServices.retail.amd64.15.8.0\lib\net45\Microsoft.AnalysisServices.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AnalysisServices.Core, Version=15.8.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.AnalysisServices.retail.amd64.15.8.0\lib\net45\Microsoft.AnalysisServices.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AnalysisServices.SPClient.Interfaces, Version=15.8.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.AnalysisServices.retail.amd64.15.8.0\lib\net45\Microsoft.AnalysisServices.SPClient.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AnalysisServices.Tabular, Version=15.8.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.AnalysisServices.retail.amd64.15.8.0\lib\net45\Microsoft.AnalysisServices.Tabular.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.AnalysisServices.Tabular.Json, Version=15.8.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Microsoft.AnalysisServices.retail.amd64.15.8.0\lib\net45\Microsoft.AnalysisServices.Tabular.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PowerArgs, Version=3.5.0.0, Culture=neutral, PublicKeyToken=26a276264bbd55b8, processorArchitecture=MSIL">
|
||||
<HintPath>packages\PowerArgs.3.5.0\lib\netstandard2.0\PowerArgs.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
73
SetUpAggs/SetUpAggs.sln
Normal file
73
SetUpAggs/SetUpAggs.sln
Normal file
@ -0,0 +1,73 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27703.2026
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SetUpAggs", "SetUpAggs.csproj", "{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}"
|
||||
EndProject
|
||||
Project("{6870E480-7721-4708-BFB8-9AE898AA21B3}") = "AdventureWorksAggs", "AW Internet Sales\AdventureWorksAggs.smproj", "{8CE414BB-95B2-4C99-9E03-51BA72086E22}"
|
||||
EndProject
|
||||
Project("{6870E480-7721-4708-BFB8-9AE898AA21B3}") = "AdventureWorksAggsProvider", "AdventureWorksAggsProvider\AdventureWorksAggsProvider.smproj", "{274B7B29-6EAE-44CE-A06B-ED91F1E52734}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x86 = Debug|x86
|
||||
Development|Any CPU = Development|Any CPU
|
||||
Development|x86 = Development|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Development|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Development|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Development|x86.ActiveCfg = Debug|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Development|x86.Build.0 = Debug|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2433EDBD-FFB1-42B9-A0BF-2DFC2953ACF1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Debug|Any CPU.ActiveCfg = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Debug|Any CPU.Build.0 = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Debug|Any CPU.Deploy.0 = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Debug|x86.ActiveCfg = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Debug|x86.Build.0 = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Debug|x86.Deploy.0 = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Development|Any CPU.ActiveCfg = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Development|x86.ActiveCfg = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Development|x86.Build.0 = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Development|x86.Deploy.0 = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Release|Any CPU.ActiveCfg = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Release|Any CPU.Build.0 = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Release|Any CPU.Deploy.0 = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Release|x86.ActiveCfg = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Release|x86.Build.0 = Development|x86
|
||||
{8CE414BB-95B2-4C99-9E03-51BA72086E22}.Release|x86.Deploy.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Debug|Any CPU.ActiveCfg = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Debug|Any CPU.Build.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Debug|Any CPU.Deploy.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Debug|x86.ActiveCfg = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Debug|x86.Build.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Debug|x86.Deploy.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Development|Any CPU.ActiveCfg = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Development|x86.ActiveCfg = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Development|x86.Build.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Development|x86.Deploy.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Release|Any CPU.ActiveCfg = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Release|Any CPU.Build.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Release|Any CPU.Deploy.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Release|x86.ActiveCfg = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Release|x86.Build.0 = Development|x86
|
||||
{274B7B29-6EAE-44CE-A06B-ED91F1E52734}.Release|x86.Deploy.0 = Development|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {6C6322A8-7B54-4A88-88DA-24C189C35847}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
6
SetUpAggs/packages.config
Normal file
6
SetUpAggs/packages.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.AnalysisServices.retail.amd64" version="15.8.0" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="12.0.1" targetFramework="net461" />
|
||||
<package id="PowerArgs" version="3.5.0" targetFramework="net461" />
|
||||
</packages>
|
Loading…
Reference in New Issue
Block a user