OptionsMapTable preparing from DacFx description,value,displayname at… (#1550)

* OptionsMapTable preparing from DacFx description,value,displayname attributes

* Review Comments addressed for options map table changes

* OptionsMapTable final changes

* Code review comments updated code changes

* Test fix: Adding missing change while splitting the PR

* DacFx vBump

* Reverted to displayName and code updates

* final:prop name changed, references updated, tests fixed, comments addressed

* Code review comments updated for name,exception etc

* updates method names

* property name changes to BooleanOptionsDictionary and comment updates

* Removed the unused properties, null cases handeled, hardcoded values are replaced
This commit is contained in:
Sai Avishkar Sreerama
2022-07-07 16:56:16 -05:00
committed by GitHub
parent 6558f2036d
commit 5663ddba68
6 changed files with 238 additions and 442 deletions

View File

@@ -14,8 +14,9 @@ using System.Collections.Generic;
namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
{ {
/// <summary> /// <summary>
/// Class to define deployment option default value and the description /// DeploymentOptionProperty class to define deployment options default value, description, and displayNames
/// </summary> /// </summary>
/// <typeparam name="T"></typeparam>
public class DeploymentOptionProperty<T> public class DeploymentOptionProperty<T>
{ {
public DeploymentOptionProperty(T value, string description = "", string displayName = "") public DeploymentOptionProperty(T value, string description = "", string displayName = "")
@@ -25,197 +26,30 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
this.DisplayName = displayName; this.DisplayName = displayName;
} }
// Default and selected value of the deployment options /// <summary>
/// Default and selected value of the deployment option
/// </summary>
public T Value { get; set; } public T Value { get; set; }
// Description of the deployment options /// <summary>
/// Description of the deployment option
/// </summary>
public string Description { get; set; } public string Description { get; set; }
// To display the options in ADS extensions UI in SchemaCompare/SQL-DB-Project/Dacpac extensions /// <summary>
/// Display name of the deployment option
/// </summary>
public string DisplayName { get; set; } public string DisplayName { get; set; }
} }
/// <summary> /// <summary>
/// Class to define deployment options. /// Class to define deployment options.
/// Keeping the order and defaults same as DacFx /// These property names will be given to the DeploymentOptions interface defined in ADS 'azuredatastudio\extensions\mssql\src\mssql.d.ts' and 'azuredatastudio\extensions\types\vscode-mssql.d.ts'
/// The default values here should also match the default values in ADS UX /// BooleanOptionsDictionary will automatically gets the newly added boolean properties from DacFx, All other types should be added here and ADS
/// NOTE: When new deployment options are added in DacFx, they need to be added here too
/// </summary> /// </summary>
public class DeploymentOptions public class DeploymentOptions
{ {
#region Properties #region Properties
public DeploymentOptionProperty<bool> IgnoreTableOptions { get; set; }
public DeploymentOptionProperty<bool> IgnoreSemicolonBetweenStatements { get; set; }
public DeploymentOptionProperty<bool> IgnoreRouteLifetime { get; set; }
public DeploymentOptionProperty<bool> IgnoreRoleMembership { get; set; }
public DeploymentOptionProperty<bool> IgnoreQuotedIdentifiers { get; set; }
public DeploymentOptionProperty<bool> IgnorePermissions { get; set; }
public DeploymentOptionProperty<bool> IgnorePartitionSchemes { get; set; }
public DeploymentOptionProperty<bool> IgnoreObjectPlacementOnPartitionScheme { get; set; }
public DeploymentOptionProperty<bool> IgnoreNotForReplication { get; set; }
public DeploymentOptionProperty<bool> IgnoreLoginSids { get; set; }
public DeploymentOptionProperty<bool> IgnoreLockHintsOnIndexes { get; set; }
public DeploymentOptionProperty<bool> IgnoreKeywordCasing { get; set; }
public DeploymentOptionProperty<bool> IgnoreIndexPadding { get; set; }
public DeploymentOptionProperty<bool> IgnoreIndexOptions { get; set; }
public DeploymentOptionProperty<bool> IgnoreIncrement { get; set; }
public DeploymentOptionProperty<bool> IgnoreIdentitySeed { get; set; }
public DeploymentOptionProperty<bool> IgnoreUserSettingsObjects { get; set; }
public DeploymentOptionProperty<bool> IgnoreFullTextCatalogFilePath { get; set; }
public DeploymentOptionProperty<bool> IgnoreWhitespace { get; set; }
public DeploymentOptionProperty<bool> IgnoreWithNocheckOnForeignKeys { get; set; }
public DeploymentOptionProperty<bool> VerifyCollationCompatibility { get; set; }
public DeploymentOptionProperty<bool> UnmodifiableObjectWarnings { get; set; }
public DeploymentOptionProperty<bool> TreatVerificationErrorsAsWarnings { get; set; }
public DeploymentOptionProperty<bool> ScriptRefreshModule { get; set; }
public DeploymentOptionProperty<bool> ScriptNewConstraintValidation { get; set; }
public DeploymentOptionProperty<bool> ScriptFileSize { get; set; }
public DeploymentOptionProperty<bool> ScriptDeployStateChecks { get; set; }
public DeploymentOptionProperty<bool> ScriptDatabaseOptions { get; set; }
public DeploymentOptionProperty<bool> ScriptDatabaseCompatibility { get; set; }
public DeploymentOptionProperty<bool> ScriptDatabaseCollation { get; set; }
public DeploymentOptionProperty<bool> RunDeploymentPlanExecutors { get; set; }
public DeploymentOptionProperty<bool> RegisterDataTierApplication { get; set; }
public DeploymentOptionProperty<bool> PopulateFilesOnFileGroups { get; set; }
public DeploymentOptionProperty<bool> NoAlterStatementsToChangeClrTypes { get; set; }
public DeploymentOptionProperty<bool> IncludeTransactionalScripts { get; set; }
public DeploymentOptionProperty<bool> IncludeCompositeObjects { get; set; }
public DeploymentOptionProperty<bool> AllowUnsafeRowLevelSecurityDataMovement { get; set; }
public DeploymentOptionProperty<bool> IgnoreWithNocheckOnCheckConstraints { get; set; }
public DeploymentOptionProperty<bool> IgnoreFillFactor { get; set; }
public DeploymentOptionProperty<bool> IgnoreFileSize { get; set; }
public DeploymentOptionProperty<bool> IgnoreFilegroupPlacement { get; set; }
public DeploymentOptionProperty<bool> DoNotAlterReplicatedObjects { get; set; }
public DeploymentOptionProperty<bool> DoNotAlterChangeDataCaptureObjects { get; set; }
public DeploymentOptionProperty<bool> DisableAndReenableDdlTriggers { get; set; }
public DeploymentOptionProperty<bool> DeployDatabaseInSingleUserMode { get; set; }
public DeploymentOptionProperty<bool> CreateNewDatabase { get; set; }
public DeploymentOptionProperty<bool> CompareUsingTargetCollation { get; set; }
public DeploymentOptionProperty<bool> CommentOutSetVarDeclarations { get; set; }
// Command timeout to 120 seconds when executing queries against SQL Server.
public DeploymentOptionProperty<int> CommandTimeout { get; set; } = new DeploymentOptionProperty<int>(120);
// LongRunningCommandTimeout 0 seconds to wait indefinitely.
public DeploymentOptionProperty<int> LongRunningCommandTimeout { get; set; } = new DeploymentOptionProperty<int>(0);
// Wait 60 seconds to lock database when executing queries against SQL Server.
public DeploymentOptionProperty<int> DatabaseLockTimeout { get; set; } = new DeploymentOptionProperty<int>(60);
public DeploymentOptionProperty<bool> BlockWhenDriftDetected { get; set; }
public DeploymentOptionProperty<bool> BlockOnPossibleDataLoss { get; set; }
public DeploymentOptionProperty<bool> BackupDatabaseBeforeChanges { get; set; }
public DeploymentOptionProperty<bool> AllowIncompatiblePlatform { get; set; }
public DeploymentOptionProperty<bool> AllowDropBlockingAssemblies { get; set; }
public DeploymentOptionProperty<string> AdditionalDeploymentContributorArguments { get; set; }
public DeploymentOptionProperty<string> AdditionalDeploymentContributors { get; set; }
public DeploymentOptionProperty<bool> DropConstraintsNotInSource { get; set; }
public DeploymentOptionProperty<bool> DropDmlTriggersNotInSource { get; set; }
public DeploymentOptionProperty<bool> DropExtendedPropertiesNotInSource { get; set; }
public DeploymentOptionProperty<bool> DropIndexesNotInSource { get; set; }
public DeploymentOptionProperty<bool> IgnoreFileAndLogFilePath { get; set; }
public DeploymentOptionProperty<bool> IgnoreExtendedProperties { get; set; }
public DeploymentOptionProperty<bool> IgnoreDmlTriggerState { get; set; }
public DeploymentOptionProperty<bool> IgnoreDmlTriggerOrder { get; set; }
public DeploymentOptionProperty<bool> IgnoreDefaultSchema { get; set; }
public DeploymentOptionProperty<bool> IgnoreDdlTriggerState { get; set; }
public DeploymentOptionProperty<bool> IgnoreDdlTriggerOrder { get; set; }
public DeploymentOptionProperty<bool> IgnoreCryptographicProviderFilePath { get; set; }
public DeploymentOptionProperty<bool> VerifyDeployment { get; set; }
public DeploymentOptionProperty<bool> IgnoreComments { get; set; }
public DeploymentOptionProperty<bool> IgnoreColumnCollation { get; set; }
public DeploymentOptionProperty<bool> IgnoreAuthorizer { get; set; }
public DeploymentOptionProperty<bool> IgnoreAnsiNulls { get; set; }
public DeploymentOptionProperty<bool> GenerateSmartDefaults { get; set; }
public DeploymentOptionProperty<bool> DropStatisticsNotInSource { get; set; }
public DeploymentOptionProperty<bool> DropRoleMembersNotInSource { get; set; }
public DeploymentOptionProperty<bool> DropPermissionsNotInSource { get; set; }
public DeploymentOptionProperty<bool> DropObjectsNotInSource { get; set; }
public DeploymentOptionProperty<bool> IgnoreColumnOrder { get; set; }
public DeploymentOptionProperty<bool> IgnoreTablePartitionOptions { get; set; } // DW Specific
public DeploymentOptionProperty<string> AdditionalDeploymentContributorPaths { get; set; }
public DeploymentOptionProperty<ObjectType[]> DoNotDropObjectTypes { get; set; }
public DeploymentOptionProperty<ObjectType[]> ExcludeObjectTypes { get; set; } = new DeploymentOptionProperty<ObjectType[]> public DeploymentOptionProperty<ObjectType[]> ExcludeObjectTypes { get; set; } = new DeploymentOptionProperty<ObjectType[]>
( (
new ObjectType[] { new ObjectType[] {
@@ -244,168 +78,17 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
} }
); );
public DeploymentOptionProperty<bool> AllowExternalLibraryPaths { get; set; }
public DeploymentOptionProperty<bool> AllowExternalLanguagePaths { get; set; }
public DeploymentOptionProperty<bool> DoNotEvaluateSqlCmdVariables { get; set; }
public DeploymentOptionProperty<bool> DisableParallelismForEnablingIndexes { get; set; }
public DeploymentOptionProperty<bool> DoNotDropWorkloadClassifiers { get; set; }
public DeploymentOptionProperty<bool> DisableIndexesForDataPhase { get; set; }
public DeploymentOptionProperty<bool> DoNotDropDatabaseWorkloadGroups { get; set; }
public DeploymentOptionProperty<bool> HashObjectNamesInLogs { get; set; }
public DeploymentOptionProperty<bool> IgnoreWorkloadClassifiers { get; set; }
public DeploymentOptionProperty<bool> IgnoreDatabaseWorkloadGroups { get; set; }
public DeploymentOptionProperty<bool> IsAlwaysEncryptedParameterizationEnabled { get; set; }
public DeploymentOptionProperty<bool> PreserveIdentityLastValues { get; set; }
public DeploymentOptionProperty<bool> RestoreSequenceCurrentValue { get; set; }
public DeploymentOptionProperty<bool> RebuildIndexesOfflineForDataPhase { get; set; }
private Dictionary<string, string> _displayNameMapDict;
#endregion
/// <summary> /// <summary>
/// Mapping the DisplayName to the dac deploy option /// BooleanOptionsDictionary contains all boolean type deployment options
/// Adding new properties here would give easy handling of new option to all extensions
/// </summary> /// </summary>
private void SetDisplayNameForOption() public Dictionary<string, DeploymentOptionProperty<bool>> BooleanOptionsDictionary { get; set; } = new Dictionary<string, DeploymentOptionProperty<bool>>(StringComparer.InvariantCultureIgnoreCase);
{
#region Display Name and Dac Options Mapping
DacDeployOptions d = new DacDeployOptions();
_displayNameMapDict = new Dictionary<string, string>();
// Ex: displayNameMapDict["DacFx Option Name"] = "ADS UI Display Name"
_displayNameMapDict[nameof(d.AdditionalDeploymentContributorArguments)] = "Additional Deployment Contributor Arguments";
_displayNameMapDict[nameof(d.AdditionalDeploymentContributorPaths)] = "Additional Deployment Contributor Paths";
_displayNameMapDict[nameof(d.AdditionalDeploymentContributors)] = "Additional Deployment Contributors";
_displayNameMapDict[nameof(d.AllowDropBlockingAssemblies)] = "Allow Drop Blocking Assemblies";
_displayNameMapDict[nameof(d.AllowExternalLanguagePaths)] = "Allow External Language Paths";
_displayNameMapDict[nameof(d.AllowExternalLibraryPaths)] = "Allow External Library Paths";
_displayNameMapDict[nameof(d.AllowIncompatiblePlatform)] = "Allow Incompatible Platform";
_displayNameMapDict[nameof(d.AllowUnsafeRowLevelSecurityDataMovement)] = "Allow Unsafe RowLevel Security Data Movement";
_displayNameMapDict[nameof(d.AzureSharedAccessSignatureToken)] = "Azure Shared Access Signature Token";
_displayNameMapDict[nameof(d.AzureStorageBlobEndpoint)] = "Azure Storage Blob Endpoint";
_displayNameMapDict[nameof(d.AzureStorageContainer)] = "Azure Storage Container";
_displayNameMapDict[nameof(d.AzureStorageKey)] = "Azure Storage Key";
_displayNameMapDict[nameof(d.AzureStorageRootPath)] = "Azure Storage Root Path";
_displayNameMapDict[nameof(d.BackupDatabaseBeforeChanges)] = "Backup Database Before Changes";
_displayNameMapDict[nameof(d.BlockOnPossibleDataLoss)] = "Block On Possible Data Loss";
_displayNameMapDict[nameof(d.BlockWhenDriftDetected)] = "Block When Drift Detected";
_displayNameMapDict[nameof(d.CommandTimeout)] = "Command Timeout";
_displayNameMapDict[nameof(d.CommentOutSetVarDeclarations)] = "Comment Out SetVar Declarations";
_displayNameMapDict[nameof(d.CompareUsingTargetCollation)] = "Compare Using Target Collation";
_displayNameMapDict[nameof(d.CreateNewDatabase)] = "Create New Database";
_displayNameMapDict[nameof(d.DatabaseLockTimeout)] = "Database Lock Timeout";
_displayNameMapDict[nameof(d.DatabaseSpecification)] = "Database Specification";
_displayNameMapDict[nameof(d.DataOperationStateProvider)] = "Data Operation State Provider";
_displayNameMapDict[nameof(d.DeployDatabaseInSingleUserMode)] = "Deploy Database In Single User Mode";
_displayNameMapDict[nameof(d.DisableAndReenableDdlTriggers)] = "Disable And Reenable Ddl Triggers";
_displayNameMapDict[nameof(d.DisableIndexesForDataPhase)] = "Disable Indexes For Data Phase";
_displayNameMapDict[nameof(d.DisableParallelismForEnablingIndexes)] = "Disable Parallelism For Enabling Indexes";
_displayNameMapDict[nameof(d.DoNotAlterChangeDataCaptureObjects)] = "Do Not Alter Change Data Capture Objects";
_displayNameMapDict[nameof(d.DoNotAlterReplicatedObjects)] = "Do Not Alter Replicated Objects";
_displayNameMapDict[nameof(d.DoNotDropDatabaseWorkloadGroups)] = "Do Not Drop Database Workload Groups";
_displayNameMapDict[nameof(d.DoNotDropObjectTypes)] = "Do Not Drop Object Types";
_displayNameMapDict[nameof(d.DoNotDropWorkloadClassifiers)] = "Do Not Drop Workload Classifiers";
_displayNameMapDict[nameof(d.DoNotEvaluateSqlCmdVariables)] = "Do Not Evaluate Sql Cmd Variables";
_displayNameMapDict[nameof(d.DropConstraintsNotInSource)] = "Drop Constraints Not In Source";
_displayNameMapDict[nameof(d.DropDmlTriggersNotInSource)] = "Drop Dml Triggers Not In Source";
_displayNameMapDict[nameof(d.DropExtendedPropertiesNotInSource)] = "Drop Extended Properties Not In Source";
_displayNameMapDict[nameof(d.DropIndexesNotInSource)] = "Drop Indexes Not In Source";
_displayNameMapDict[nameof(d.DropObjectsNotInSource)] = "Drop Objects Not In Source";
_displayNameMapDict[nameof(d.DropPermissionsNotInSource)] = "Drop Permissions Not In Source";
_displayNameMapDict[nameof(d.DropRoleMembersNotInSource)] = "Drop Role Members Not In Source";
_displayNameMapDict[nameof(d.DropStatisticsNotInSource)] = "Drop Statistics Not In Source";
_displayNameMapDict[nameof(d.EnclaveAttestationProtocol)] = "Enclave Attestation Protocol";
_displayNameMapDict[nameof(d.EnclaveAttestationUrl)] = "Enclave Attestation Url";
_displayNameMapDict[nameof(d.ExcludeObjectTypes)] = "Exclude Object Types";
_displayNameMapDict[nameof(d.GenerateSmartDefaults)] = "Generate Smart Defaults";
_displayNameMapDict[nameof(d.HashObjectNamesInLogs)] = "Hash Object Names In Logs";
_displayNameMapDict[nameof(d.IgnoreAnsiNulls)] = "Ignore Ansi Nulls";
_displayNameMapDict[nameof(d.IgnoreAuthorizer)] = "Ignore Authorizer";
_displayNameMapDict[nameof(d.IgnoreColumnCollation)] = "Ignore Column Collation";
_displayNameMapDict[nameof(d.IgnoreColumnOrder)] = "Ignore Column Order";
_displayNameMapDict[nameof(d.IgnoreComments)] = "Ignore Comments";
_displayNameMapDict[nameof(d.IgnoreCryptographicProviderFilePath)] = "Ignore Cryptographic Provider File Path";
_displayNameMapDict[nameof(d.IgnoreDatabaseWorkloadGroups)] = "Ignore Database Workload Groups";
_displayNameMapDict[nameof(d.IgnoreDdlTriggerOrder)] = "Ignore Ddl Trigger Order";
_displayNameMapDict[nameof(d.IgnoreDdlTriggerState)] = "Ignore Ddl Trigger State";
_displayNameMapDict[nameof(d.IgnoreDefaultSchema)] = "Ignore Default Schema";
_displayNameMapDict[nameof(d.IgnoreDmlTriggerOrder)] = "Ignore Dml Trigger Order";
_displayNameMapDict[nameof(d.IgnoreDmlTriggerState)] = "Ignore Dml Trigger State";
_displayNameMapDict[nameof(d.IgnoreExtendedProperties)] = "Ignore Extended Properties";
_displayNameMapDict[nameof(d.IgnoreFileAndLogFilePath)] = "Ignore File And Log File Path";
_displayNameMapDict[nameof(d.IgnoreFileSize)] = "Ignore File Size";
_displayNameMapDict[nameof(d.IgnoreFilegroupPlacement)] = "Ignore File Group Placement";
_displayNameMapDict[nameof(d.IgnoreFillFactor)] = "Ignore Fill Factor";
_displayNameMapDict[nameof(d.IgnoreFullTextCatalogFilePath)] = "Ignore Full Text Catalog File Path";
_displayNameMapDict[nameof(d.IgnoreIdentitySeed)] = "Ignore Identity Seed";
_displayNameMapDict[nameof(d.IgnoreIncrement)] = "Ignore Increment";
_displayNameMapDict[nameof(d.IgnoreIndexOptions)] = "Ignore Index Options";
_displayNameMapDict[nameof(d.IgnoreIndexPadding)] = "Ignore Index Padding";
_displayNameMapDict[nameof(d.IgnoreKeywordCasing)] = "Ignore Keyword Casing";
_displayNameMapDict[nameof(d.IgnoreLockHintsOnIndexes)] = "IgnoreLock Hints On Indexes";
_displayNameMapDict[nameof(d.IgnoreLoginSids)] = "IgnoreLogin Sids";
_displayNameMapDict[nameof(d.IgnoreNotForReplication)] = "IgnoreNotForReplication";
_displayNameMapDict[nameof(d.IgnoreObjectPlacementOnPartitionScheme)] = "Ignore Object Placement On Partition Scheme";
_displayNameMapDict[nameof(d.IgnorePartitionSchemes)] = "Ignore Partition Schemes";
_displayNameMapDict[nameof(d.IgnorePermissions)] = "Ignore Permissions";
_displayNameMapDict[nameof(d.IgnoreQuotedIdentifiers)] = "Ignore Quoted Identifiers";
_displayNameMapDict[nameof(d.IgnoreRoleMembership)] = "Ignore Role Membership";
_displayNameMapDict[nameof(d.IgnoreRouteLifetime)] = "Ignore Route Lifetime";
_displayNameMapDict[nameof(d.IgnoreSemicolonBetweenStatements)] = "Ignore Semicolon Between Statements";
_displayNameMapDict[nameof(d.IgnoreTableOptions)] = "Ignore Table Options";
_displayNameMapDict[nameof(d.IgnoreTablePartitionOptions)] = "Ignore Table Partition Options";
_displayNameMapDict[nameof(d.IgnoreUserSettingsObjects)] = "Ignore User Settings Objects";
_displayNameMapDict[nameof(d.IgnoreWhitespace)] = "Ignore Whitespace";
_displayNameMapDict[nameof(d.IgnoreWithNocheckOnCheckConstraints)] = "Ignore With Nocheck On Check Constraints";
_displayNameMapDict[nameof(d.IgnoreWithNocheckOnForeignKeys)] = "Ignore With Nocheck On Foreign Keys";
_displayNameMapDict[nameof(d.IgnoreWorkloadClassifiers)] = "Ignore Workload Classifiers";
_displayNameMapDict[nameof(d.IncludeCompositeObjects)] = "Include Composite Objects";
_displayNameMapDict[nameof(d.IncludeTransactionalScripts)] = "Include Transactional Scripts";
_displayNameMapDict[nameof(d.IsAlwaysEncryptedParameterizationEnabled)] = "Is Always Encrypted Parameterization Enabled";
_displayNameMapDict[nameof(d.LongRunningCommandTimeout)] = "Long Running Command Timeout";
_displayNameMapDict[nameof(d.NoAlterStatementsToChangeClrTypes)] = "No Alter Statements To Change Clr Types";
_displayNameMapDict[nameof(d.PopulateFilesOnFileGroups)] = "Populate Files On File Groups";
_displayNameMapDict[nameof(d.PreserveIdentityLastValues)] = "Preserve Identity Last Values";
_displayNameMapDict[nameof(d.RebuildIndexesOfflineForDataPhase)] = "Rebuild Indexes Offline For Data Phase";
_displayNameMapDict[nameof(d.RegisterDataTierApplication)] = "Register Data Tier Application";
_displayNameMapDict[nameof(d.RestoreSequenceCurrentValue)] = "Restore Sequence Current Value";
_displayNameMapDict[nameof(d.RunDeploymentPlanExecutors)] = "Run Deployment Plan Executors";
_displayNameMapDict[nameof(d.ScriptDatabaseCollation)] = "Script Database Collation";
_displayNameMapDict[nameof(d.ScriptDatabaseCompatibility)] = "Script Database Compatibility";
_displayNameMapDict[nameof(d.ScriptDatabaseOptions)] = "Script Database Options";
_displayNameMapDict[nameof(d.ScriptDeployStateChecks)] = "Script Deploy State Checks";
_displayNameMapDict[nameof(d.ScriptFileSize)] = "Script File Size";
_displayNameMapDict[nameof(d.ScriptNewConstraintValidation)] = "Script New Constraint Validation";
_displayNameMapDict[nameof(d.ScriptRefreshModule)] = "Script Refresh Module";
_displayNameMapDict[nameof(d.SqlCommandVariableValues)] = "Sql Command Variable Values";
_displayNameMapDict[nameof(d.TreatVerificationErrorsAsWarnings)] = "Treat Verification Errors As Warnings";
_displayNameMapDict[nameof(d.UnmodifiableObjectWarnings)] = "Unmodifiable Object Warnings";
_displayNameMapDict[nameof(d.VerifyCollationCompatibility)] = "Verify Collation Compatibility";
_displayNameMapDict[nameof(d.VerifyDeployment)] = "Verify Deployment";
#endregion #endregion
}
public DeploymentOptions() public DeploymentOptions()
{ {
DacDeployOptions options = new DacDeployOptions(); DacDeployOptions options = new DacDeployOptions();
// Setting Display names for all dacDeploy options
SetDisplayNameForOption();
// Adding these defaults to ensure behavior similarity with other tools. Dacfx and SSMS import/export wizards use these defaults. // Adding these defaults to ensure behavior similarity with other tools. Dacfx and SSMS import/export wizards use these defaults.
// Tracking the full fix : https://github.com/microsoft/azuredatastudio/issues/5599 // Tracking the full fix : https://github.com/microsoft/azuredatastudio/issues/5599
options.AllowDropBlockingAssemblies = true; options.AllowDropBlockingAssemblies = true;
@@ -416,26 +99,13 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
options.IgnoreKeywordCasing = false; options.IgnoreKeywordCasing = false;
options.IgnoreSemicolonBetweenStatements = false; options.IgnoreSemicolonBetweenStatements = false;
PropertyInfo[] deploymentOptionsProperties = this.GetType().GetProperties(); // Initializing the default boolean type options to the BooleanOptionsDictionary
// Not considering DacFx default ExcludeObjectTypes, as it has some STS defaults which needs to be considered here, DacFx defaults are only considered for InitializeFromProfile(), where options are loading from profile
foreach (var deployOptionsProp in deploymentOptionsProperties) InitializeBooleanTypeOptions(options);
{
var prop = options.GetType().GetProperty(deployOptionsProp.Name);
// Note that we set excluded object types here since dacfx has this value as null;
if (prop != null && deployOptionsProp.Name != "ExcludeObjectTypes")
{
// Setting DacFx default values to the generic deployment options properties.
SetGenericDeployOptionProps(prop, options, deployOptionsProp);
}
}
} }
public DeploymentOptions(DacDeployOptions options) public DeploymentOptions(DacDeployOptions options)
{ {
// Setting Display names for all dacDeploy options
SetDisplayNameForOption();
SetOptions(options); SetOptions(options);
} }
@@ -480,35 +150,66 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx.Contracts
SetOptions(options); SetOptions(options);
} }
/// <summary>
/// Populates BooleanOptionsDictionary with the boolean type properties
/// </summary>
/// <param name="options"></param>
public void InitializeBooleanTypeOptions(DacDeployOptions options)
{
PropertyInfo[] dacDeploymentOptionsProperties = options.GetType().GetProperties();
foreach (PropertyInfo prop in dacDeploymentOptionsProperties)
{
if (prop != null && prop.PropertyType == typeof(System.Boolean))
{
object setProp = GetDeploymentOptionProp(prop, options);
this.BooleanOptionsDictionary[prop.Name] = (DeploymentOptionProperty<bool>)setProp;
}
}
}
public void SetOptions(DacDeployOptions options) public void SetOptions(DacDeployOptions options)
{ {
System.Reflection.PropertyInfo[] deploymentOptionsProperties = this.GetType().GetProperties(); // Set the default options properties
InitializeBooleanTypeOptions(options);
InitializeNonBooleanTypeOptions(options);
}
foreach (var deployOptionsProp in deploymentOptionsProperties) /// <summary>
/// Preparing all non boolean properties (except BooleanOptionsDictionary)
/// </summary>
/// <param name="options"></param>
public void InitializeNonBooleanTypeOptions(DacDeployOptions options)
{ {
var prop = options.GetType().GetProperty(deployOptionsProp.Name); // preparing remaining properties
// Note that we set excluded object types here since dacfx has this value as null; PropertyInfo[] deploymentOptionsProperties = this.GetType().GetProperties();
if (prop != null) foreach (PropertyInfo deployOptionsProp in deploymentOptionsProperties)
{ {
SetGenericDeployOptionProps(prop, options, deployOptionsProp); if (deployOptionsProp.Name != nameof(DeploymentOptions.BooleanOptionsDictionary))
{
PropertyInfo prop = options.GetType().GetProperty(deployOptionsProp.Name);
object setProp = GetDeploymentOptionProp(prop, options);
deployOptionsProp.SetValue(this, setProp);
} }
} }
} }
/// <summary> /// <summary>
/// Sets the Value and Description to all properties /// Prepares and returns the value and description of a property
/// </summary> /// </summary>
/// <param name="prop"></param> /// <param name="prop"></param>
/// <param name="val"></param> /// <param name="options"></param>
/// <param name="deployOptionsProp"></param> public object GetDeploymentOptionProp(PropertyInfo prop, DacDeployOptions options)
public void SetGenericDeployOptionProps(PropertyInfo prop, DacDeployOptions options, PropertyInfo deployOptionsProp)
{ {
var val = prop.GetValue(options); var val = prop.GetValue(options);
var attribute = prop.GetCustomAttributes<DescriptionAttribute>(true).FirstOrDefault(); DescriptionAttribute descriptionAttribute = prop.GetCustomAttributes<DescriptionAttribute>().FirstOrDefault();
DisplayNameAttribute displayNameAttribute = prop.GetCustomAttributes<DisplayNameAttribute>().FirstOrDefault();
Type type = val != null ? typeof(DeploymentOptionProperty<>).MakeGenericType(val.GetType()) Type type = val != null ? typeof(DeploymentOptionProperty<>).MakeGenericType(val.GetType())
: typeof(DeploymentOptionProperty<>).MakeGenericType(prop.PropertyType); : typeof(DeploymentOptionProperty<>).MakeGenericType(prop.PropertyType);
object setProp = Activator.CreateInstance(type, val, attribute.Description,_displayNameMapDict[deployOptionsProp.Name]);
deployOptionsProp.SetValue(this, setProp); object setProp = Activator.CreateInstance(type, val,
(descriptionAttribute != null ? descriptionAttribute.Description : ""),
(displayNameAttribute != null ? displayNameAttribute.DisplayName : ""));
return setProp;
} }
public static DeploymentOptions GetDefaultSchemaCompareOptions() public static DeploymentOptions GetDefaultSchemaCompareOptions()

View File

@@ -4,6 +4,7 @@
// //
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@@ -14,6 +15,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts; using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts; using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
{ {
@@ -23,32 +25,61 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
/// </summary> /// </summary>
internal static class SchemaCompareUtils internal static class SchemaCompareUtils
{ {
/// <summary>
/// Converts DeploymentOptions used in STS and ADS to DacDeployOptions which can be passed to the DacFx apis
/// </summary>
/// <param name="deploymentOptions"></param>
/// <returns>DacDeployOptions</returns
internal static DacDeployOptions CreateSchemaCompareOptions(DeploymentOptions deploymentOptions) internal static DacDeployOptions CreateSchemaCompareOptions(DeploymentOptions deploymentOptions)
{
try
{ {
PropertyInfo[] deploymentOptionsProperties = deploymentOptions.GetType().GetProperties(); PropertyInfo[] deploymentOptionsProperties = deploymentOptions.GetType().GetProperties();
DacDeployOptions dacOptions = new DacDeployOptions(); DacDeployOptions dacOptions = new DacDeployOptions();
foreach (var deployOptionsProp in deploymentOptionsProperties) Type propType = dacOptions.GetType();
Dictionary<string, DeploymentOptionProperty<bool>> booleanOptionsDictionary = new Dictionary<string, DeploymentOptionProperty<bool>>();
foreach (PropertyInfo deployOptionsProp in deploymentOptionsProperties)
{ {
var prop = dacOptions.GetType().GetProperty(deployOptionsProp.Name); var prop = propType.GetProperty(deployOptionsProp.Name);
if (prop != null) if (prop != null)
{ {
var val = deployOptionsProp.GetValue(deploymentOptions); var val = deployOptionsProp.GetValue(deploymentOptions);
var selectedVal = val.GetType().GetProperty("Value").GetValue(val); var selectedVal = val.GetType().GetProperty("Value").GetValue(val);
// JSON.NET by default reads Number type as Int64, deserializing an object type to dacOptions of Int32 type required to convert into Int32 from Int64. // Set the excludeObjectTypes values to the DacDeployOptions
// If not converted setting value(Int64) to dacOption(Int32) will throw {"Object of type 'System.Int64' cannot be converted to type 'System.Int32'."}. if (selectedVal != null && deployOptionsProp.Name == nameof(deploymentOptions.ExcludeObjectTypes))
// As these integer type options are non-editable and are not availbale in ADS to update, integer overflow exception will not be happening here.
if (selectedVal != null && selectedVal.GetType() == typeof(System.Int64))
{ {
selectedVal = Convert.ToInt32(selectedVal); prop.SetValue(dacOptions, selectedVal);
}
} }
// 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<string, DeploymentOptionProperty<bool>>;
}
}
// Iterating through the updated boolean options coming from the booleanOptionsDictionary and assigning them to DacDeployOptions
foreach (KeyValuePair<string, DeploymentOptionProperty<bool>> deployOptionsProp in booleanOptionsDictionary)
{
var prop = propType.GetProperty(deployOptionsProp.Key);
if (prop != null)
{
var selectedVal = deployOptionsProp.Value.Value;
prop.SetValue(dacOptions, selectedVal); prop.SetValue(dacOptions, selectedVal);
} }
} }
return dacOptions; 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) internal static DiffEntry CreateDiffEntry(SchemaDifference difference, DiffEntry parent)
{ {

View File

@@ -18,6 +18,7 @@ using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.ServiceLayer.Test.Common; using Microsoft.SqlTools.ServiceLayer.Test.Common;
using NUnit.Framework; using NUnit.Framework;
using Moq; using Moq;
using System.Reflection;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DacFx namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DacFx
{ {
@@ -586,11 +587,13 @@ FROM MissingEdgeHubInputStream'";
UpgradeExisting = true, UpgradeExisting = true,
DeploymentOptions = new DeploymentOptions() DeploymentOptions = new DeploymentOptions()
{ {
DropObjectsNotInSource = new DeploymentOptionProperty<bool>(false),
ExcludeObjectTypes = new DeploymentOptionProperty<ObjectType[]>(new[] { ObjectType.Views }) ExcludeObjectTypes = new DeploymentOptionProperty<ObjectType[]>(new[] { ObjectType.Views })
} }
}; };
// Updating the BooleanOptionsDictionary since it has all the boolean type options
deployParams.DeploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.DropObjectsNotInSource)].Value = false;
// expect table3 to not have been dropped and view1 to not have been created // expect table3 to not have been dropped and view1 to not have been created
await VerifyDeployWithOptions(deployParams, targetDb, service, result.ConnectionInfo, expectedTableResult: "table3", expectedViewResult: null); await VerifyDeployWithOptions(deployParams, targetDb, service, result.ConnectionInfo, expectedTableResult: "table3", expectedViewResult: null);
@@ -664,11 +667,13 @@ FROM MissingEdgeHubInputStream'";
DatabaseName = targetDb.DatabaseName, DatabaseName = targetDb.DatabaseName,
DeploymentOptions = new DeploymentOptions() DeploymentOptions = new DeploymentOptions()
{ {
DropObjectsNotInSource = new DeploymentOptionProperty<bool>(false),
ExcludeObjectTypes = new DeploymentOptionProperty<ObjectType[]>(new[] { ObjectType.Views }) ExcludeObjectTypes = new DeploymentOptionProperty<ObjectType[]>(new[] { ObjectType.Views })
} }
}; };
// Updating the BooleanOptionsDictionary since it has all the boolean type properties
generateScriptFalseOptionParams.DeploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.DropObjectsNotInSource)].Value = false;
var generateScriptFalseOptionOperation = new GenerateDeployScriptOperation(generateScriptFalseOptionParams, result.ConnectionInfo); var generateScriptFalseOptionOperation = new GenerateDeployScriptOperation(generateScriptFalseOptionParams, result.ConnectionInfo);
service.PerformOperation(generateScriptFalseOptionOperation, TaskExecutionMode.Execute); service.PerformOperation(generateScriptFalseOptionOperation, TaskExecutionMode.Execute);
@@ -682,7 +687,6 @@ FROM MissingEdgeHubInputStream'";
DatabaseName = targetDb.DatabaseName, DatabaseName = targetDb.DatabaseName,
DeploymentOptions = new DeploymentOptions() DeploymentOptions = new DeploymentOptions()
{ {
DropObjectsNotInSource = new DeploymentOptionProperty<bool>(true),
ExcludeObjectTypes = new DeploymentOptionProperty<ObjectType[]>( new[] { ObjectType.Views }) ExcludeObjectTypes = new DeploymentOptionProperty<ObjectType[]>( new[] { ObjectType.Views })
} }
}; };
@@ -727,10 +731,10 @@ FROM MissingEdgeHubInputStream'";
DeploymentOptions expectedResults = DeploymentOptions.GetDefaultPublishOptions(); DeploymentOptions expectedResults = DeploymentOptions.GetDefaultPublishOptions();
expectedResults.ExcludeObjectTypes = null; expectedResults.ExcludeObjectTypes = null;
expectedResults.IncludeCompositeObjects = new DeploymentOptionProperty<bool>(true); expectedResults.BooleanOptionsDictionary[nameof(DacDeployOptions.IncludeCompositeObjects)].Value = true;
expectedResults.BlockOnPossibleDataLoss = new DeploymentOptionProperty<bool>(true); expectedResults.BooleanOptionsDictionary[nameof(DacDeployOptions.BlockOnPossibleDataLoss)].Value = true;
expectedResults.AllowIncompatiblePlatform = new DeploymentOptionProperty<bool>(true); expectedResults.BooleanOptionsDictionary[nameof(DacDeployOptions.AllowIncompatiblePlatform)].Value = true;
expectedResults.DisableIndexesForDataPhase = new DeploymentOptionProperty<bool>(false); expectedResults.BooleanOptionsDictionary[nameof(DacDeployOptions.DisableIndexesForDataPhase)].Value = false;
var dacfxRequestContext = new Mock<RequestContext<DacFxOptionsResult>>(); var dacfxRequestContext = new Mock<RequestContext<DacFxOptionsResult>>();
dacfxRequestContext.Setup((RequestContext<DacFxOptionsResult> x) => x.SendResult(It.Is<DacFxOptionsResult>((result) => ValidateOptions(expectedResults, result.DeploymentOptions) == true))).Returns(Task.FromResult(new object())); dacfxRequestContext.Setup((RequestContext<DacFxOptionsResult> x) => x.SendResult(It.Is<DacFxOptionsResult>((result) => ValidateOptions(expectedResults, result.DeploymentOptions) == true))).Returns(Task.FromResult(new object()));
@@ -755,7 +759,7 @@ FROM MissingEdgeHubInputStream'";
{ {
DeploymentOptions expectedResults = DeploymentOptions.GetDefaultPublishOptions(); DeploymentOptions expectedResults = DeploymentOptions.GetDefaultPublishOptions();
expectedResults.ExcludeObjectTypes = null; expectedResults.ExcludeObjectTypes = null;
expectedResults.DisableIndexesForDataPhase = new DeploymentOptionProperty<bool>(false); expectedResults.BooleanOptionsDictionary["DisableIndexesForDataPhase"].Value = false;
var dacfxRequestContext = new Mock<RequestContext<DacFxOptionsResult>>(); var dacfxRequestContext = new Mock<RequestContext<DacFxOptionsResult>>();
dacfxRequestContext.Setup((RequestContext<DacFxOptionsResult> x) => x.SendResult(It.Is<DacFxOptionsResult>((result) => ValidateOptions(expectedResults, result.DeploymentOptions) == true))).Returns(Task.FromResult(new object())); dacfxRequestContext.Setup((RequestContext<DacFxOptionsResult> x) => x.SendResult(It.Is<DacFxOptionsResult>((result) => ValidateOptions(expectedResults, result.DeploymentOptions) == true))).Returns(Task.FromResult(new object()));
@@ -842,14 +846,17 @@ Streaming query statement contains a reference to missing output stream 'Missing
private bool ValidateOptions(DeploymentOptions expected, DeploymentOptions actual) private bool ValidateOptions(DeploymentOptions expected, DeploymentOptions actual)
{ {
System.Reflection.PropertyInfo[] deploymentOptionsProperties = expected.GetType().GetProperties(); System.Reflection.PropertyInfo[] deploymentOptionsProperties = expected.GetType().GetProperties();
foreach (var v in deploymentOptionsProperties) var booleanOptionsDictionary = new Dictionary<string, DeploymentOptionProperty<bool>>();
foreach (PropertyInfo v in deploymentOptionsProperties)
{
if (v.Name != nameof(DeploymentOptions.BooleanOptionsDictionary))
{ {
var defaultP = v.GetValue(expected); var defaultP = v.GetValue(expected);
var defaultPValue = defaultP != null ? defaultP.GetType().GetProperty("Value").GetValue(defaultP): defaultP; var defaultPValue = defaultP != null ? defaultP.GetType().GetProperty("Value").GetValue(defaultP) : defaultP;
var actualP = v.GetValue(actual); var actualP = v.GetValue(actual);
var actualPValue = actualP.GetType().GetProperty("Value").GetValue(actualP); var actualPValue = actualP.GetType().GetProperty("Value").GetValue(actualP);
if (v.Name == "ExcludeObjectTypes") if (v.Name == nameof(DeploymentOptions.ExcludeObjectTypes))
{ {
Assert.True((defaultP as ObjectType[])?.Length == (actualP as ObjectType[])?.Length, "Number of excluded objects is different not equal"); Assert.True((defaultP as ObjectType[])?.Length == (actualP as ObjectType[])?.Length, "Number of excluded objects is different not equal");
} }
@@ -861,6 +868,14 @@ Streaming query statement contains a reference to missing output stream 'Missing
, $"Actual Property from Service is not equal to default property for {v.Name}, Actual value: {actualPValue} and Default value: {defaultPValue}"); , $"Actual Property from Service is not equal to default property for {v.Name}, Actual value: {actualPValue} and Default value: {defaultPValue}");
} }
} }
else
{
booleanOptionsDictionary = v.GetValue(expected) as Dictionary<string, DeploymentOptionProperty<bool>>;
}
}
// Verify expected and actual DeploymentOptions BooleanOptionsDictionary
VerifyExpectedAndActualBooleanOptionsDictionary(booleanOptionsDictionary, actual.BooleanOptionsDictionary);
return true; return true;
} }
@@ -895,5 +910,21 @@ Streaming query statement contains a reference to missing output stream 'Missing
File.Delete(filePath); File.Delete(filePath);
} }
} }
/// <summary>
/// Verify expected and actual DeploymentOptions BooleanOptionsDictionary values
/// </summary>
/// <param name="expectedBooleanOptionsDictionary"></param>
/// <param name="actualBooleanOptionsDictionary"></param>
public void VerifyExpectedAndActualBooleanOptionsDictionary(Dictionary<string, DeploymentOptionProperty<bool>> expectedBooleanOptionsDictionary, Dictionary<string, DeploymentOptionProperty<bool>> actualBooleanOptionsDictionary)
{
foreach (KeyValuePair<string, DeploymentOptionProperty<bool>> optionRow in expectedBooleanOptionsDictionary)
{
var expectedValue = optionRow.Value.Value;
var actualValue = actualBooleanOptionsDictionary[optionRow.Key].Value;
Assert.That(actualValue, Is.EqualTo(expectedValue), $"Actual Property from Service is not equal to default property for {optionRow.Key}");
}
}
} }
} }

View File

@@ -72,7 +72,7 @@ END
private DeploymentOptions GetIgnoreColumnOptions() private DeploymentOptions GetIgnoreColumnOptions()
{ {
var options = new DeploymentOptions(); var options = new DeploymentOptions();
options.IgnoreColumnOrder = new DeploymentOptionProperty<bool>(true); options.BooleanOptionsDictionary[nameof(DacDeployOptions.IgnoreColumnOrder)].Value = true;
return options; return options;
} }

View File

@@ -20,6 +20,7 @@ using System.Threading.Tasks;
using NUnit.Framework; using NUnit.Framework;
using static Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility.LiveConnectionHelper; using static Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility.LiveConnectionHelper;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.SqlServer.Dac;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SchemaCompare namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SchemaCompare
{ {
@@ -1823,22 +1824,21 @@ WITH VALUES
{ {
SourceEndpointInfo = sourceInfo, SourceEndpointInfo = sourceInfo,
TargetEndpointInfo = targetInfo, TargetEndpointInfo = targetInfo,
DeploymentOptions = new DeploymentOptions() DeploymentOptions = new DeploymentOptions(),
{
// change some random ones explicitly
AllowDropBlockingAssemblies = new DeploymentOptionProperty<bool>(true),
DropConstraintsNotInSource = new DeploymentOptionProperty<bool>(true),
IgnoreAnsiNulls = new DeploymentOptionProperty<bool>(true),
NoAlterStatementsToChangeClrTypes = new DeploymentOptionProperty<bool>(false),
PopulateFilesOnFileGroups = new DeploymentOptionProperty<bool>(false),
VerifyDeployment = new DeploymentOptionProperty<bool>(false),
DisableIndexesForDataPhase = new DeploymentOptionProperty<bool>(false)
},
ScmpFilePath = filePath, ScmpFilePath = filePath,
ExcludedSourceObjects = schemaCompareObjectIds, ExcludedSourceObjects = schemaCompareObjectIds,
ExcludedTargetObjects = null, ExcludedTargetObjects = null,
}; };
// change some random ones explicitly
schemaCompareParams.DeploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.AllowDropBlockingAssemblies)].Value = true;
schemaCompareParams.DeploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.DropConstraintsNotInSource)].Value = true;
schemaCompareParams.DeploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.IgnoreAnsiNulls)].Value = true;
schemaCompareParams.DeploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.NoAlterStatementsToChangeClrTypes)].Value = false;
schemaCompareParams.DeploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.PopulateFilesOnFileGroups)].Value = false;
schemaCompareParams.DeploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.VerifyDeployment)].Value = false;
schemaCompareParams.DeploymentOptions.BooleanOptionsDictionary[nameof(DacDeployOptions.DisableIndexesForDataPhase)].Value = false;
SchemaCompareSaveScmpOperation schemaCompareOperation = new SchemaCompareSaveScmpOperation(schemaCompareParams, result.ConnectionInfo, result.ConnectionInfo); SchemaCompareSaveScmpOperation schemaCompareOperation = new SchemaCompareSaveScmpOperation(schemaCompareParams, result.ConnectionInfo, result.ConnectionInfo);
schemaCompareOperation.Execute(TaskExecutionMode.Execute); schemaCompareOperation.Execute(TaskExecutionMode.Execute);

View File

@@ -6,6 +6,7 @@
using Microsoft.SqlServer.Dac; using Microsoft.SqlServer.Dac;
using Microsoft.SqlTools.ServiceLayer.DacFx; using Microsoft.SqlTools.ServiceLayer.DacFx;
using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts; using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts;
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.DacFx;
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility; using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
using Microsoft.SqlTools.ServiceLayer.TaskServices; using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts; using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
@@ -14,6 +15,8 @@ using NUnit.Framework;
using System; using System;
using System.IO; using System.IO;
using static Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility.LiveConnectionHelper; using static Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility.LiveConnectionHelper;
using System.Collections.Generic;
using System.Reflection;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SchemaCompare namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SchemaCompare
{ {
@@ -129,43 +132,49 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SchemaCompare
// TODO: update with new options. Tracking issue: https://github.com/microsoft/azuredatastudio/issues/15336 // TODO: update with new options. Tracking issue: https://github.com/microsoft/azuredatastudio/issues/15336
//Assert.True(deploymentOptionsProperties.Length == dacDeployProperties.Length - 2, $"Number of properties is not same Deployment options : {deploymentOptionsProperties.Length} DacFx options : {dacDeployProperties.Length}"); //Assert.True(deploymentOptionsProperties.Length == dacDeployProperties.Length - 2, $"Number of properties is not same Deployment options : {deploymentOptionsProperties.Length} DacFx options : {dacDeployProperties.Length}");
foreach (var deployOptionsProp in deploymentOptionsProperties) foreach (PropertyInfo deployOptionsProp in deploymentOptionsProperties)
{
if (deployOptionsProp.Name != nameof(DeploymentOptions.BooleanOptionsDictionary))
{ {
var dacProp = dacDeployOptions.GetType().GetProperty(deployOptionsProp.Name); var dacProp = dacDeployOptions.GetType().GetProperty(deployOptionsProp.Name);
Assert.True(dacProp != null, $"DacDeploy property not present for {deployOptionsProp.Name}"); Assert.That(dacProp, Is.Not.Null, $"DacDeploy property not present for {deployOptionsProp.Name}");
var deployOptionsValue = deployOptionsProp.GetValue(deploymentOptions); var defaultP = deployOptionsProp.GetValue(deploymentOptions);
var changedDacValue = deployOptionsValue != null ? deployOptionsValue.GetType().GetProperty("Value").GetValue(deployOptionsValue) : deployOptionsValue; var defaultPValue = defaultP != null ? defaultP.GetType().GetProperty("Value").GetValue(defaultP) : defaultP;
var dafaultDacValue = dacProp.GetValue(dacDeployOptions); var actualPValue = dacProp.GetValue(dacDeployOptions);
if (deployOptionsProp.Name != "ExcludeObjectTypes") // do not compare for ExcludeObjectTypes because it will be different if (deployOptionsProp.Name != nameof(DeploymentOptions.ExcludeObjectTypes)) // do not compare for ExcludeObjectTypes because it will be different
{ {
Assert.True((deployOptionsValue == null && dafaultDacValue == null) // Verifying expected and actual deployment options properties are equal
|| deployOptionsValue.Equals(dafaultDacValue) Assert.True((defaultPValue == null && String.IsNullOrEmpty(actualPValue as string))
|| changedDacValue == null && (dafaultDacValue as string) == string.Empty || (defaultPValue).Equals(actualPValue)
|| changedDacValue == null && dafaultDacValue == null , $"DacFx DacDeploy property not equal to Tools Service DeploymentOptions for {deployOptionsProp.Name}, Actual value: {actualPValue} and Default value: {defaultPValue}");
|| (changedDacValue).Equals(dafaultDacValue)
, $"DacFx DacDeploy property not equal to Tools Service DeploymentOptions for { deployOptionsProp.Name}, SchemaCompareOptions value: {changedDacValue} and DacDeployOptions value: {dafaultDacValue} ");
} }
} }
} }
// Verify the booleanOptionsDictionary with the DacDeployOptions property values
VerifyBooleanOptionsDictionary(deploymentOptions.BooleanOptionsDictionary, dacDeployOptions);
}
internal static bool ValidateOptionsEqualsDefault(SchemaCompareOptionsResult options) internal static bool ValidateOptionsEqualsDefault(SchemaCompareOptionsResult options)
{ {
DeploymentOptions defaultOpt = new DeploymentOptions(); DeploymentOptions defaultOpt = new DeploymentOptions();
DeploymentOptions actualOpt = options.DefaultDeploymentOptions; DeploymentOptions actualOpt = options.DefaultDeploymentOptions;
System.Reflection.PropertyInfo[] deploymentOptionsProperties = defaultOpt.GetType().GetProperties(); System.Reflection.PropertyInfo[] deploymentOptionsProperties = defaultOpt.GetType().GetProperties();
foreach (var v in deploymentOptionsProperties) foreach (PropertyInfo v in deploymentOptionsProperties)
{
if (v.Name != nameof(DeploymentOptions.BooleanOptionsDictionary))
{ {
var defaultP = v.GetValue(defaultOpt); var defaultP = v.GetValue(defaultOpt);
var defaultPValue = defaultP != null ? defaultP.GetType().GetProperty("Value").GetValue(defaultP) : defaultP; var defaultPValue = defaultP != null ? defaultP.GetType().GetProperty("Value").GetValue(defaultP) : defaultP;
var actualP = v.GetValue(actualOpt); var actualP = v.GetValue(actualOpt);
var actualPValue = actualP.GetType().GetProperty("Value").GetValue(actualP); var actualPValue = actualP.GetType().GetProperty("Value").GetValue(actualP);
if (v.Name == "ExcludeObjectTypes") if (v.Name == nameof(DeploymentOptions.ExcludeObjectTypes))
{ {
Assert.True((defaultPValue as ObjectType[]).Length == (actualPValue as ObjectType[]).Length, $"Number of excluded objects is different; expected: {(defaultPValue as ObjectType[]).Length} actual: {(actualPValue as ObjectType[]).Length}"); Assert.That((defaultPValue as ObjectType[]).Length, Is.EqualTo((actualPValue as ObjectType[]).Length), $"Number of excluded objects is different; expected: {(defaultPValue as ObjectType[]).Length} actual: {(actualPValue as ObjectType[]).Length}");
} }
else else
{ {
@@ -175,7 +184,31 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SchemaCompare
, $"Actual Property from Service is not equal to default property for {v.Name}, Actual value: {actualPValue} and Default value: {defaultPValue}"); , $"Actual Property from Service is not equal to default property for {v.Name}, Actual value: {actualPValue} and Default value: {defaultPValue}");
} }
} }
}
// Verify the default booleanOptionsDictionary with the SchemaCompareOptionsResult options property values
DacFxServiceTests dacFxServiceTests = new DacFxServiceTests();
dacFxServiceTests.VerifyExpectedAndActualBooleanOptionsDictionary(defaultOpt.BooleanOptionsDictionary, options.DefaultDeploymentOptions.BooleanOptionsDictionary);
return true; return true;
} }
/// <summary>
/// Validates the DeploymentOptions booleanOptionsDictionary with the DacDeployOptions
/// </summary>
/// <param name="expectedBooleanOptionsDictionary"></param>
/// <param name="dacDeployOptions"></param>
private static void VerifyBooleanOptionsDictionary(Dictionary<string, DeploymentOptionProperty<bool>> expectedBooleanOptionsDictionary, DacDeployOptions dacDeployOptions)
{
foreach (KeyValuePair<string, DeploymentOptionProperty<bool>> optionRow in expectedBooleanOptionsDictionary)
{
var dacProp = dacDeployOptions.GetType().GetProperty(optionRow.Key);
Assert.That(dacProp, Is.Not.Null, $"DacDeploy property not present for {optionRow.Key}");
var actualValue = dacProp.GetValue(dacDeployOptions);
var expectedValue = optionRow.Value.Value;
Assert.That(actualValue, Is.EqualTo(expectedValue), $"Actual Property from Service is not equal to default property for {optionRow.Key}");
}
}
} }
} }