diff --git a/Packages.props b/Packages.props index 6aaa7403..1bd05d5e 100644 --- a/Packages.props +++ b/Packages.props @@ -22,7 +22,7 @@ - + diff --git a/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxService.cs b/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxService.cs index 05bdbe68..10976b22 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxService.cs @@ -329,7 +329,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx DacProfile profile = new DacProfile(); profile.TargetDatabaseName = parameters.DatabaseName; profile.TargetConnectionString = parameters.ConnectionString; - //TODO: Set deploy options to pass on to DacFx + profile.DeployOptions = DacFxUtils.CreateDeploymentOptions(parameters.DeploymentOptions); if (parameters.SqlCommandVariableValues != null) { @@ -338,7 +338,6 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx profile.DeployOptions.SqlCommandVariableValues[key] = parameters.SqlCommandVariableValues[key]; } } - //TODO: Add return from Save with success/fail status profile.Save(parameters.ProfilePath); } }, requestContext); diff --git a/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxUtils.cs b/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxUtils.cs new file mode 100644 index 00000000..ff623fc6 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/DacFx/DacFxUtils.cs @@ -0,0 +1,89 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using Microsoft.SqlServer.Dac; +using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.DacFx +{ + internal static class DacFxUtils + { + /// + /// Converts DeploymentOptions used in STS and ADS to DacDeployOptions which can be passed to the DacFx apis + /// + /// + /// DacDeployOptions> booleanOptionsDictionary = new Dictionary>(); + + foreach (PropertyInfo deployOptionsProp in deploymentOptionsProperties) + { + var prop = propType.GetProperty(deployOptionsProp.Name); + // Set the excludeObjectTypes values to the DacDeployOptions + if (prop != null && deployOptionsProp.Name == nameof(deploymentOptions.ExcludeObjectTypes)) + { + List finalExcludeObjects = new List { }; + var val = deployOptionsProp.GetValue(deploymentOptions); + string[] excludeObjectTypeOptionsArray = (string[])val.GetType().GetProperty("Value").GetValue(val); + + if (excludeObjectTypeOptionsArray != null) + { + foreach (string objectTypeValue in excludeObjectTypeOptionsArray) + { + ObjectType objectTypeName = new ObjectType(); + + if (objectTypeValue != null && Enum.TryParse(objectTypeValue, ignoreCase: true, out objectTypeName)) + { + finalExcludeObjects.Add(objectTypeName); + } + else + { + Logger.Write(TraceEventType.Error, string.Format($"{objectTypeValue} is not part of ObjectTypes enum")); + } + } + // set final values to excludeObjectType property + prop.SetValue(dacOptions, finalExcludeObjects.ToArray()); + } + } + + // BooleanOptionsDictionary has all the deployment options and is being processed separately in the second iteration by collecting here + if (deployOptionsProp.Name == nameof(deploymentOptions.BooleanOptionsDictionary)) + { + booleanOptionsDictionary = deploymentOptions.BooleanOptionsDictionary as Dictionary>; + } + } + + // Iterating through the updated boolean options coming from the booleanOptionsDictionary and assigning them to DacDeployOptions + foreach (KeyValuePair> deployOptionsProp in booleanOptionsDictionary) + { + var prop = propType.GetProperty(deployOptionsProp.Key); + if (prop != null) + { + var selectedVal = deployOptionsProp.Value.Value; + prop.SetValue(dacOptions, selectedVal); + } + } + return dacOptions; + } + catch (Exception e) + { + Logger.Write(TraceEventType.Error, string.Format("Schema compare create options model failed: {0}", e.Message)); + throw; + } + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/DacFx/DeployOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/DacFx/DeployOperation.cs index dea78394..81e8f62b 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DacFx/DeployOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DacFx/DeployOperation.cs @@ -7,7 +7,6 @@ using Microsoft.SqlServer.Dac; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts; -using Microsoft.SqlTools.ServiceLayer.SchemaCompare; using Microsoft.SqlTools.Utility; namespace Microsoft.SqlTools.ServiceLayer.DacFx @@ -28,7 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx public override void Execute() { DacPackage dacpac = DacPackage.Load(this.Parameters.PackageFilePath); - DacDeployOptions options = this.Parameters.DeploymentOptions != null ? SchemaCompareUtils.CreateSchemaCompareOptions(this.Parameters.DeploymentOptions) : this.GetDefaultDeployOptions(); + DacDeployOptions options = this.Parameters.DeploymentOptions != null ? DacFxUtils.CreateDeploymentOptions(this.Parameters.DeploymentOptions) : this.GetDefaultDeployOptions(); if (this.Parameters.SqlCommandVariableValues != null) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/DacFx/GenerateDeployScriptOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/DacFx/GenerateDeployScriptOperation.cs index 83c933a8..4043dc28 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/DacFx/GenerateDeployScriptOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/DacFx/GenerateDeployScriptOperation.cs @@ -9,7 +9,6 @@ using System.Threading; using Microsoft.SqlServer.Dac; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts; -using Microsoft.SqlTools.ServiceLayer.SchemaCompare; using Microsoft.SqlTools.ServiceLayer.TaskServices; using Microsoft.SqlTools.Utility; @@ -36,7 +35,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx PublishOptions publishOptions = new PublishOptions(); publishOptions.GenerateDeploymentReport = this.Parameters.GenerateDeploymentReport; publishOptions.CancelToken = this.CancellationToken; - publishOptions.DeployOptions = this.Parameters.DeploymentOptions != null ? SchemaCompareUtils.CreateSchemaCompareOptions(this.Parameters.DeploymentOptions) : this.GetDefaultDeployOptions(); + publishOptions.DeployOptions = this.Parameters.DeploymentOptions != null ? DacFxUtils.CreateDeploymentOptions(this.Parameters.DeploymentOptions) : this.GetDefaultDeployOptions(); if (this.Parameters.SqlCommandVariableValues != null) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs index cf22f7fc..1b20bb38 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs @@ -6,6 +6,7 @@ #nullable disable using Microsoft.SqlServer.Dac.Compare; using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.DacFx; using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts; using Microsoft.SqlTools.ServiceLayer.TaskServices; using Microsoft.SqlTools.Utility; @@ -92,7 +93,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare if (this.Parameters.DeploymentOptions != null) { - comparison.Options = SchemaCompareUtils.CreateSchemaCompareOptions(this.Parameters.DeploymentOptions); + comparison.Options = DacFxUtils.CreateDeploymentOptions(this.Parameters.DeploymentOptions); } // for testing diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareSaveScmpOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareSaveScmpOperation.cs index c7322039..c04bcca0 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareSaveScmpOperation.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareSaveScmpOperation.cs @@ -6,6 +6,7 @@ #nullable disable using Microsoft.SqlServer.Dac.Compare; using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.DacFx; using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts; using Microsoft.SqlTools.ServiceLayer.TaskServices; using Microsoft.SqlTools.Utility; @@ -87,7 +88,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare if (this.Parameters.DeploymentOptions != null) { - comparison.Options = SchemaCompareUtils.CreateSchemaCompareOptions(this.Parameters.DeploymentOptions); + comparison.Options = DacFxUtils.CreateDeploymentOptions(this.Parameters.DeploymentOptions); } comparison.SaveToFile(this.Parameters.ScmpFilePath, true); diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareUtils.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareUtils.cs index fbbc7880..f1de615f 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareUtils.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareUtils.cs @@ -6,19 +6,15 @@ #nullable disable using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; -using System.Reflection; using System.Text.RegularExpressions; using Microsoft.SqlServer.Dac; using Microsoft.SqlServer.Dac.Compare; using Microsoft.SqlServer.Dac.Model; using Microsoft.SqlTools.ServiceLayer.Connection; -using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts; using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts; using Microsoft.SqlTools.ServiceLayer.Utility; using static Microsoft.SqlTools.Utility.SqlConstants; -using Microsoft.SqlTools.Utility; namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare { @@ -28,77 +24,6 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare /// internal static class SchemaCompareUtils { - /// - /// Converts DeploymentOptions used in STS and ADS to DacDeployOptions which can be passed to the DacFx apis - /// - /// - /// DacDeployOptions> booleanOptionsDictionary = new Dictionary>(); - - foreach (PropertyInfo deployOptionsProp in deploymentOptionsProperties) - { - var prop = propType.GetProperty(deployOptionsProp.Name); - // Set the excludeObjectTypes values to the DacDeployOptions - if (prop != null && deployOptionsProp.Name == nameof(deploymentOptions.ExcludeObjectTypes)) - { - List finalExcludeObjects = new List { }; - var val = deployOptionsProp.GetValue(deploymentOptions); - string[] excludeObjectTypeOptionsArray = (string[])val.GetType().GetProperty("Value").GetValue(val); - - if (excludeObjectTypeOptionsArray != null) - { - foreach(string objectTypeValue in excludeObjectTypeOptionsArray) - { - ObjectType objectTypeName = new ObjectType(); - - if (objectTypeValue != null && Enum.TryParse(objectTypeValue, ignoreCase: true, out objectTypeName)) - { - finalExcludeObjects.Add(objectTypeName); - } - else - { - Logger.Write(TraceEventType.Error, string.Format($"{objectTypeValue} is not part of ObjectTypes enum")); - } - } - // set final values to excludeObjectType property - prop.SetValue(dacOptions, finalExcludeObjects.ToArray()); - } - } - - // BooleanOptionsDictionary has all the deployment options and is being processed separately in the second iteration by collecting here - if (deployOptionsProp.Name == nameof(deploymentOptions.BooleanOptionsDictionary)) - { - booleanOptionsDictionary = deploymentOptions.BooleanOptionsDictionary as Dictionary>; - } - } - - // Iterating through the updated boolean options coming from the booleanOptionsDictionary and assigning them to DacDeployOptions - foreach (KeyValuePair> deployOptionsProp in booleanOptionsDictionary) - { - var prop = propType.GetProperty(deployOptionsProp.Key); - if (prop != null) - { - var selectedVal = deployOptionsProp.Value.Value; - prop.SetValue(dacOptions, selectedVal); - } - } - return dacOptions; - } - catch (Exception e) - { - Logger.Write(TraceEventType.Error, string.Format("Schema compare create options model failed: {0}", e.Message)); - throw; - } - } - internal static DiffEntry CreateDiffEntry(SchemaDifference difference, DiffEntry parent) { if (difference == null) diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/DacFxServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/DacFxServiceTests.cs index 1993a651..b8d0061e 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/DacFxServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/DacFxServiceTests.cs @@ -882,6 +882,17 @@ Streaming query statement contains a reference to missing output stream 'Missing string profileFilePath = Path.Combine(folderPath, fileName); string expectedFile = Path.Combine(publishProfileFolder, fileName); + DeploymentOptions deploymentOptions = DeploymentOptions.GetDefaultPublishOptions(); + + // a few extra options get added in the publish.xml file, because of the defaults that are set in STS for maintaining compatibility with ADS and SSDT + // these defaults are defined in ..\sqltoolsservice\src\Microsoft.SqlTools.ServiceLayer\DacFx\Contracts\DeploymentOptions.cs + deploymentOptions.ExcludeObjectTypes = new DeploymentOptionProperty(new[] { nameof(ObjectType.Views) }); + deploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.CreateNewDatabase)].Value = true; + deploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.DropConstraintsNotInSource)].Value = false; + deploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.ScriptFileSize)].Value = true; + deploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.VerifyDeployment)].Value = false; + deploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.AllowIncompatiblePlatform)].Value = true; + var savePublishProfileParams = new SavePublishProfileParams { ProfilePath = profileFilePath, @@ -890,7 +901,8 @@ Streaming query statement contains a reference to missing output stream 'Missing SqlCommandVariableValues = new Dictionary() { { "testvar", "testval" } - } + }, + DeploymentOptions = deploymentOptions }; MockRequest requestMock = new(); diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/validateSavePublishProfile.publish.xml b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/validateSavePublishProfile.publish.xml index 1d000656..4185238c 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/validateSavePublishProfile.publish.xml +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DacFx/PublishProfiles/validateSavePublishProfile.publish.xml @@ -3,6 +3,18 @@ testDb testConnString + True + True + False + True + True + True + False + False + True + False + True + True 1