diff --git a/BismNormalizer/AlmToolkit/ComparisonForm.cs b/BismNormalizer/AlmToolkit/ComparisonForm.cs index 47799ab..9cae884 100644 --- a/BismNormalizer/AlmToolkit/ComparisonForm.cs +++ b/BismNormalizer/AlmToolkit/ComparisonForm.cs @@ -194,18 +194,10 @@ namespace AlmToolkit btnGenerateScript.Enabled = true; _compareState = CompareState.Validated; - // This method needs to be moved out of comparison control during clean up - //ComparisonCtrl.SetValidatedState(); } private bool ShowConnectionsForm() { - //if (ComparisonCtrl.CompareState != CompareState.NotCompared) - //{ - // - // ComparisonCtrl.RefreshSkipSelections(); - //} - if (_compareState != CompareState.NotCompared) { //just in case user has some selections, store them to the SkipSelections collection @@ -672,7 +664,7 @@ namespace AlmToolkit private void btnUpdate_Click(object sender, EventArgs e) { - if (MessageBox.Show($"Are you sure you want to update target?", Utils.AssemblyProduct, MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) + if (MessageBox.Show($"Are you sure you want to update the target?", Utils.AssemblyProduct, MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) { return; } diff --git a/BismNormalizer/BismNormalizer/BismNormalizer.csproj b/BismNormalizer/BismNormalizer/BismNormalizer.csproj index d19c62a..2149958 100644 --- a/BismNormalizer/BismNormalizer/BismNormalizer.csproj +++ b/BismNormalizer/BismNormalizer/BismNormalizer.csproj @@ -210,6 +210,7 @@ + @@ -230,6 +231,7 @@ + @@ -250,10 +252,10 @@ Connections.cs - - - - + + + + Form diff --git a/BismNormalizer/BismNormalizer/TabularCompare/ConnectionInfo.cs b/BismNormalizer/BismNormalizer/TabularCompare/ConnectionInfo.cs index 2d13c4f..d88a02b 100644 --- a/BismNormalizer/BismNormalizer/TabularCompare/ConnectionInfo.cs +++ b/BismNormalizer/BismNormalizer/TabularCompare/ConnectionInfo.cs @@ -451,7 +451,7 @@ namespace BismNormalizer.TabularCompare bool exceptionLoadingFile = false; try { - tomDatabase = TOM.JsonSerializer.DeserializeDatabase(File.ReadAllText(_bimFile)); + tomDatabase = OpenDatabaseFromFile(); } catch { @@ -497,7 +497,7 @@ namespace BismNormalizer.TabularCompare } } - Server amoServer = new Server(); + Microsoft.AnalysisServices.Server amoServer = new Microsoft.AnalysisServices.Server(); try { amoServer.Connect(BuildConnectionString()); @@ -546,7 +546,7 @@ namespace BismNormalizer.TabularCompare throw new ConnectionException($"Analysis Server {this.ServerName} is not running in Tabular mode"); } - Database amoDatabase = null; + Microsoft.AnalysisServices.Database amoDatabase = null; if (this.DatabaseName == "" && this.ServerName.ToUpper().StartsWith("localhost:".ToUpper())) { //PBI Desktop doesn't have db name yet @@ -700,6 +700,27 @@ $@"{{ amoDatabase.DirectQueryMode == DirectQueryMode.DirectQuery || amoDatabase.DirectQueryMode == DirectQueryMode.InMemoryWithDirectQuery || amoDatabase.DirectQueryMode == DirectQueryMode.DirectQueryWithInMemory); } + /// + /// Check if file is PBIT and return instantiated TOM database. + /// + /// + public TOM.Database OpenDatabaseFromFile() + { + TOM.Database tomDatabase; + string modelJson; + if (_bimFile.ToUpper().EndsWith(".PBIT")) + { + PowerBiTemplate pbit = new PowerBiTemplate(_bimFile); + modelJson = pbit.ModelJson; + } + else + { + modelJson = File.ReadAllText(_bimFile); + } + tomDatabase = TOM.JsonSerializer.DeserializeDatabase(modelJson); + return tomDatabase; + } + /// /// Build connection string. /// diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ManagedIpHelper.cs b/BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/ManagedIpHelper.cs similarity index 99% rename from BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ManagedIpHelper.cs rename to BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/ManagedIpHelper.cs index 3bf88fb..ac70766 100644 --- a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ManagedIpHelper.cs +++ b/BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/ManagedIpHelper.cs @@ -6,6 +6,7 @@ using System.Net; using System.Net.NetworkInformation; using System.Runtime.InteropServices; +//namespace DaxStudio.UI.Utils namespace BismNormalizer.TabularCompare.UI.DesktopInstances { diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/PowerBIHelper.cs b/BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/PowerBIHelper.cs similarity index 99% rename from BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/PowerBIHelper.cs rename to BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/PowerBIHelper.cs index 552e221..51e15cb 100644 --- a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/PowerBIHelper.cs +++ b/BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/PowerBIHelper.cs @@ -4,6 +4,7 @@ using System.Diagnostics; //using Serilog; using System.Security.Principal; +//namespace DaxStudio.UI.Utils namespace BismNormalizer.TabularCompare.UI.DesktopInstances { public enum EmbeddedSSASIcon diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ProcessExtensions.cs b/BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/ProcessExtensions.cs similarity index 96% rename from BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ProcessExtensions.cs rename to BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/ProcessExtensions.cs index 8b14a55..e16d1f6 100644 --- a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/ProcessExtensions.cs +++ b/BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/ProcessExtensions.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Management; +//namespace DaxStudio.UI.Extensions namespace BismNormalizer.TabularCompare.UI.DesktopInstances { public static class ProcessExtensions diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/WindowTitle.cs b/BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/WindowTitle.cs similarity index 99% rename from BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/WindowTitle.cs rename to BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/WindowTitle.cs index 83c1797..94ee0a7 100644 --- a/BismNormalizer/BismNormalizer/TabularCompare/UI/DesktopInstances/WindowTitle.cs +++ b/BismNormalizer/BismNormalizer/TabularCompare/DesktopInstances/WindowTitle.cs @@ -6,6 +6,7 @@ using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; +//namespace DaxStudio.Common namespace BismNormalizer.TabularCompare.UI.DesktopInstances { public class WindowTitle diff --git a/BismNormalizer/BismNormalizer/TabularCompare/PowerBiTemplate.cs b/BismNormalizer/BismNormalizer/TabularCompare/PowerBiTemplate.cs new file mode 100644 index 0000000..625cae5 --- /dev/null +++ b/BismNormalizer/BismNormalizer/TabularCompare/PowerBiTemplate.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +//namespace TabularEditor.TOMWrapper.PowerBI +namespace BismNormalizer.TabularCompare +{ + /// + /// Represents a Power BI Template (.pbit) file. Constructor loads the file into memory. Provides properties for + /// getting and setting the data model json, as well as saving the content back to a .pbit file. + /// + internal class PowerBiTemplate + { + MemoryStream fileData = new MemoryStream(); + public PowerBiTemplate(string path) + { + try + { + using (var fs = new FileStream(path, FileMode.Open)) + { + fs.CopyTo(fileData); + fileData.Seek(0, SeekOrigin.Begin); + using (var za = new ZipArchive(fileData, ZipArchiveMode.Read, true)) + { + var modelEntry = za.Entries.FirstOrDefault(e => e.Name == "DataModelSchema"); + if (modelEntry != null) + { + using (var sr = new StreamReader(modelEntry.Open(), Encoding.Unicode, true, 1024, true)) + { + _modelJson = sr.ReadToEnd(); + } + } + else + throw new Exception(); + } + } + } + catch + { + throw new InvalidOperationException("This file is not a valid PBIX / PBIT file."); + } + } + + private string _modelJson; + public string ModelJson + { + get + { + return _modelJson; + } + set + { + SetModelJson(value); + _modelJson = value; + } + } + + private void SetModelJson(string modelJson) + { + try + { + fileData.Seek(0, SeekOrigin.Begin); + using (var za = new ZipArchive(fileData, ZipArchiveMode.Update, true)) + { + var modelEntry = za.Entries.FirstOrDefault(e => e.Name == "DataModelSchema"); + if (modelEntry != null) + { + var modelEntryName = modelEntry.FullName; + modelEntry.Delete(); + modelEntry = za.CreateEntry(modelEntryName); + var unicodeNoBom = new UnicodeEncoding(false, false); + using (var sw = new StreamWriter(modelEntry.Open(), unicodeNoBom, 1024, true)) + { + sw.Write(modelJson); + } + } + else + throw new Exception(); + } + } + catch + { + throw new InvalidOperationException("This file is not a valid PBIX / PBIT file."); + } + } + + public void SaveAs(string path) + { + fileData.Seek(0, SeekOrigin.Begin); + using (var fs = File.Open(path, FileMode.OpenOrCreate, FileAccess.Write)) + { + fs.SetLength(0); + fileData.CopyTo(fs); + } + } + } +} diff --git a/BismNormalizer/BismNormalizer/TabularCompare/TabularMetadata/TabularModel.cs b/BismNormalizer/BismNormalizer/TabularCompare/TabularMetadata/TabularModel.cs index 38063b9..f3960fe 100644 --- a/BismNormalizer/BismNormalizer/TabularCompare/TabularMetadata/TabularModel.cs +++ b/BismNormalizer/BismNormalizer/TabularCompare/TabularMetadata/TabularModel.cs @@ -59,7 +59,7 @@ namespace BismNormalizer.TabularCompare.TabularMetadata if (_connectionInfo.UseBimFile) { - _database = JsonSerializer.DeserializeDatabase(File.ReadAllText(_connectionInfo.BimFile)); + _database = _connectionInfo.OpenDatabaseFromFile(); } else { @@ -1767,21 +1767,44 @@ namespace BismNormalizer.TabularCompare.TabularMetadata //serialize db to json SerializeOptions options = new SerializeOptions(); - options.IgnoreInferredProperties = true; - options.IgnoreInferredObjects = true; - options.IgnoreTimestamps = true; + bool isPbit = (_connectionInfo.UseBimFile && _connectionInfo.BimFile.ToUpper().EndsWith(".PBIT")); + + if (isPbit) + { + options.IgnoreInferredProperties = false; + options.IgnoreInferredObjects = false; + options.IgnoreTimestamps = false; + } + else + { + options.IgnoreInferredProperties = true; + options.IgnoreInferredObjects = true; + options.IgnoreTimestamps = true; + } options.SplitMultilineStrings = true; string json = JsonSerializer.SerializeDatabase(_database, options); //replace db name with "SemanticModel" - JObject jDb = JObject.Parse(json); - jDb["name"] = "SemanticModel"; - jDb["id"] = "SemanticModel"; - json = jDb.ToString(); + if (!isPbit) + { + JObject jDb = JObject.Parse(json); + jDb["name"] = "SemanticModel"; + jDb["id"] = "SemanticModel"; + json = jDb.ToString(); + } if (_connectionInfo.UseBimFile) { - File.WriteAllText(_connectionInfo.BimFile, json); + if (isPbit) + { + PowerBiTemplate pbit = new PowerBiTemplate(_connectionInfo.BimFile); + pbit.ModelJson = json; + pbit.SaveAs(_connectionInfo.BimFile); + } + else + { + File.WriteAllText(_connectionInfo.BimFile, json); + } } else { @@ -2153,7 +2176,7 @@ namespace BismNormalizer.TabularCompare.TabularMetadata //script db to json string json = JsonScripter.ScriptCreateOrReplace(_database); - if (_connectionInfo.UseProject) + if (_connectionInfo.UseProject || _connectionInfo.UseBimFile) { //replace db/cube name/id with name of deploymnet db from the project file JObject jScript = JObject.Parse(json); @@ -2164,6 +2187,16 @@ namespace BismNormalizer.TabularCompare.TabularMetadata ((JObject)createOrReplace["database"])["name"] = _connectionInfo.DeploymentServerDatabase; ((JObject)createOrReplace["database"])["id"] = _connectionInfo.DeploymentServerDatabase; } + else if (_connectionInfo.UseBimFile) + { + try + { + string fileName = Path.GetFileNameWithoutExtension(_connectionInfo.BimFile); + ((JObject)createOrReplace["object"])["database"] = fileName; + ((JObject)createOrReplace["database"])["name"] = fileName; + } + catch { } + } json = jScript.ToString(); } diff --git a/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.cs b/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.cs index 1fbb5e4..89cc7d0 100644 --- a/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.cs +++ b/BismNormalizer/BismNormalizer/TabularCompare/UI/ConnectionsAlmt.cs @@ -492,7 +492,7 @@ namespace BismNormalizer.TabularCompare.UI { OpenFileDialog ofd = new OpenFileDialog(); ofd.InitialDirectory = (String.IsNullOrEmpty(Settings.Default.LastBimFileLocation) ? Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) : Settings.Default.LastBimFileLocation); - ofd.Filter = "BIM Files (.bim)|*.bim|All files (*.*)|*.*"; + ofd.Filter = "PBIT files (.pbit)|*.pbit|BIM files (.bim)|*.bim|All files (*.*)|*.*"; ofd.Title = "Open"; return ofd; }