Applying Changes to SQL Database Projects and Using Projects in Comparison (#1282)

* passing initial testing

* update local project from database

* update local project

* update project from database

* update project from database

* update project from database

* update project from database

* update project from database

* update project from database

* update project from database

* update project from database

* update project from database

* update project from database

* Bump .net version

* PR feedback

Co-authored-by: Noureldine Yehia <t-nyehia@microsoft.com>
This commit is contained in:
Benjin Dubishar
2021-11-04 21:36:59 -04:00
committed by GitHub
parent eda47bc0a4
commit 6acda6e1e6
12 changed files with 1036 additions and 103 deletions

View File

@@ -13,7 +13,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts
/// <summary>
/// Parameters for a schema compare generate script request.
/// </summary>
public class SchemaCompareGenerateScriptParams : SchemaComparePublishChangesParams
public class SchemaCompareGenerateScriptParams : SchemaComparePublishDatabaseChangesParams
{
}

View File

@@ -2,6 +2,7 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.ServiceLayer.Utility;
@@ -9,9 +10,9 @@ using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts
{
/// <summary>
/// Parameters for a schema compare publish changes request.
/// Parameters for a schema compare publish database changes request.
/// </summary>
public class SchemaComparePublishChangesParams
public class SchemaComparePublishDatabaseChangesParams
{
/// <summary>
/// Operation id of the schema compare operation
@@ -35,11 +36,11 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts
}
/// <summary>
/// Defines the Schema Compare publish changes request type
/// Defines the Schema Compare publish database changes request type
/// </summary>
class SchemaComparePublishChangesRequest
class SchemaComparePublishDatabaseChangesRequest
{
public static readonly RequestType<SchemaComparePublishChangesParams, ResultStatus> Type =
RequestType<SchemaComparePublishChangesParams, ResultStatus>.Create("schemaCompare/publish");
public static readonly RequestType<SchemaComparePublishDatabaseChangesParams, ResultStatus> Type =
RequestType<SchemaComparePublishDatabaseChangesParams, ResultStatus>.Create("schemaCompare/publishDatabase");
}
}

View File

@@ -0,0 +1,47 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlServer.Dac;
using Microsoft.SqlServer.Dac.Compare;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts
{
/// <summary>
/// Parameters for a schema compare publish project changes request.
/// </summary>
public class SchemaComparePublishProjectChangesParams
{
/// <summary>
/// Operation id of the schema compare operation
/// </summary>
public string OperationId { get; set; }
/// <summary>
/// Path of project folder
/// </summary>
public string TargetProjectPath { get; set; }
/// <summary>
/// folder structure of target folder
/// </summary>
public DacExtractTarget TargetFolderStructure { get; set; }
/// <summary>
/// Execution mode for the operation. Default is execution
/// </summary>
public TaskExecutionMode TaskExecutionMode { get; set; }
}
/// <summary>
/// Defines the Schema Compare publish project changes request type
/// </summary>
class SchemaComparePublishProjectChangesRequest
{
public static readonly RequestType<SchemaComparePublishProjectChangesParams, SchemaComparePublishProjectResult> Type =
RequestType<SchemaComparePublishProjectChangesParams, SchemaComparePublishProjectResult>.Create("schemaCompare/publishProject");
}
}

View File

@@ -12,12 +12,19 @@ using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts
{
/// <summary>
/// Types of schema compare endpoints
/// </summary>
public enum SchemaCompareEndpointType
{
Database,
Project,
Dacpac
}
/// <summary>
/// Info needed from endpoints for schema comparison
/// </summary>
public class SchemaCompareEndpointInfo
{
/// <summary>
@@ -25,6 +32,21 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts
/// </summary>
public SchemaCompareEndpointType EndpointType { get; set; }
/// <summary>
/// Gets or sets the project file path
/// </summary>
public string ProjectFilePath { get; set; }
/// <summary>
/// Gets or sets the scripts included in project
/// </summary>
public string[] TargetScripts { get; set; }
/// <summary>
/// Gets or sets the project data schema provider
/// </summary>
public string DataSchemaProvider { get; set; }
/// <summary>
/// Gets or sets package filepath
/// </summary>

View File

@@ -100,13 +100,17 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
{
SchemaCompareEndpointInfo endpointInfo = new SchemaCompareEndpointInfo();
// if the endpoint is a dacpac we don't need to parse the xml
SchemaCompareDacpacEndpoint dacpacEndpoint = endpoint as SchemaCompareDacpacEndpoint;
if (dacpacEndpoint != null)
// if the endpoint is a dacpac or a project we don't need to parse the xml
if (endpoint is SchemaCompareDacpacEndpoint dacpacEndpoint)
{
endpointInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
endpointInfo.PackageFilePath = dacpacEndpoint.FilePath;
}
else if (endpoint is SchemaCompareProjectEndpoint projectEndpoint)
{
endpointInfo.EndpointType = SchemaCompareEndpointType.Project;
endpointInfo.ProjectFilePath = projectEndpoint.ProjectFilePath;
}
else
{
// need to parse xml to get connection string of database
@@ -131,7 +135,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
}
catch (Exception e)
{
ErrorMessage = string.Format(SR.OpenScmpConnectionBasedModelParsingError, ((SchemaCompareDatabaseEndpoint)endpoint).DatabaseName,e.Message);
ErrorMessage = string.Format(SR.OpenScmpConnectionBasedModelParsingError, ((SchemaCompareDatabaseEndpoint)endpoint).DatabaseName, e.Message);
Logger.Write(TraceEventType.Error, string.Format("Schema compare open scmp operation failed during xml parsing with exception {0}", e.Message));
throw;
}

View File

@@ -2,79 +2,38 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Threading;
using Microsoft.SqlServer.Dac.Compare;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.Utility;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
{
/// <summary>
/// Class to represent an in-progress schema compare publish changes operation
/// </summary>
class SchemaComparePublishChangesOperation : ITaskOperation
abstract class SchemaComparePublishChangesOperation : ITaskOperation
{
private CancellationTokenSource cancellation = new CancellationTokenSource();
/// <summary>
/// Gets the unique id associated with this instance.
/// </summary>
public string OperationId { get; private set; }
public SchemaComparePublishChangesParams Parameters { get; }
protected CancellationToken CancellationToken { get { return this.cancellation.Token; } }
public string ErrorMessage { get; set; }
public SqlTask SqlTask { get; set; }
public SchemaComparisonResult ComparisonResult { get; set; }
public SchemaComparePublishResult PublishResult { get; set; }
public string ErrorMessage { get; set; }
public SchemaComparePublishChangesOperation(SchemaComparePublishChangesParams parameters, SchemaComparisonResult comparisonResult)
protected CancellationToken CancellationToken { get { return cancellation.Token; } }
protected readonly CancellationTokenSource cancellation = new();
public SchemaComparePublishChangesOperation(SchemaComparisonResult comparisonResult)
{
Validate.IsNotNull("parameters", parameters);
this.Parameters = parameters;
Validate.IsNotNull("comparisonResult", comparisonResult);
this.ComparisonResult = comparisonResult;
Validate.IsNotNull(nameof(comparisonResult), comparisonResult);
ComparisonResult = comparisonResult;
}
public abstract void Execute(TaskExecutionMode mode);
public void Execute(TaskExecutionMode mode)
{
if (this.CancellationToken.IsCancellationRequested)
{
throw new OperationCanceledException(this.CancellationToken);
}
try
{
this.PublishResult = this.ComparisonResult.PublishChangesToTarget(this.CancellationToken);
if (!this.PublishResult.Success)
{
// Sending only errors and warnings - because overall message might be too big for task view
ErrorMessage = string.Join(Environment.NewLine, this.PublishResult.Errors.Where(x => x.MessageType == SqlServer.Dac.DacMessageType.Error || x.MessageType == SqlServer.Dac.DacMessageType.Warning));
throw new Exception(ErrorMessage);
}
}
catch (Exception e)
{
ErrorMessage = e.Message;
Logger.Write(TraceEventType.Error, string.Format("Schema compare publish changes operation {0} failed with exception {1}", this.OperationId, e.Message));
throw;
}
}
// The schema compare public api doesn't currently take a cancellation token so the operation can't be cancelled
public void Cancel()
{
this.cancellation.Cancel();
cancellation.Cancel();
}
}
}

View File

@@ -0,0 +1,56 @@
//
// 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.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.SqlServer.Dac.Compare;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.Utility;
using Microsoft.SqlServer.Dac;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
{
/// <summary>
/// Class to represent an in-progress schema compare publish database changes operation
/// </summary>
class SchemaComparePublishDatabaseChangesOperation : SchemaComparePublishChangesOperation
{
public SchemaComparePublishDatabaseChangesParams Parameters { get; }
public SchemaComparePublishResult PublishResult { get; set; }
public SchemaComparePublishDatabaseChangesOperation(SchemaComparePublishDatabaseChangesParams parameters, SchemaComparisonResult comparisonResult) : base(comparisonResult)
{
Validate.IsNotNull(nameof(parameters), parameters);
Parameters = parameters;
}
public override void Execute(TaskExecutionMode mode)
{
CancellationToken.ThrowIfCancellationRequested();
try
{
PublishResult = ComparisonResult.PublishChangesToDatabase(CancellationToken);
if (!PublishResult.Success)
{
// Sending only errors and warnings - because overall message might be too big for task view
ErrorMessage = String.Join(Environment.NewLine, this.PublishResult.Errors.Where(x => x.MessageType == SqlServer.Dac.DacMessageType.Error || x.MessageType == SqlServer.Dac.DacMessageType.Warning));
throw new DacServicesException(ErrorMessage);
}
}
catch (Exception e)
{
ErrorMessage = e.Message;
Logger.Write(TraceEventType.Error, string.Format("Schema compare publish database changes operation {0} failed with exception {1}", this.OperationId, e.Message));
throw;
}
}
}
}

View File

@@ -0,0 +1,57 @@
//
// 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.Diagnostics;
using System.Threading;
using Microsoft.SqlServer.Dac;
using Microsoft.SqlServer.Dac.Compare;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
{
/// <summary>
/// Class to represent an in-progress schema compare publish project changes operation
/// </summary>
class SchemaComparePublishProjectChangesOperation: SchemaComparePublishChangesOperation
{
public SchemaComparePublishProjectChangesParams Parameters { get; }
public SchemaComparePublishProjectResult PublishResult { get; set; }
public SchemaComparePublishProjectChangesOperation(SchemaComparePublishProjectChangesParams parameters, SchemaComparisonResult comparisonResult) : base(comparisonResult)
{
Validate.IsNotNull(nameof(parameters), parameters);
Parameters = parameters;
}
public override void Execute(TaskExecutionMode mode)
{
if (CancellationToken.IsCancellationRequested)
{
throw new OperationCanceledException(CancellationToken);
}
try
{
PublishResult = ComparisonResult.PublishChangesToProject(Parameters.TargetProjectPath, Parameters.TargetFolderStructure);
if (!PublishResult.Success)
{
ErrorMessage = PublishResult.ErrorMessage;
throw new DacServicesException(ErrorMessage);
}
}
catch (Exception e)
{
ErrorMessage = e.Message;
Logger.Write(TraceEventType.Error, string.Format("Schema compare publish project changes operation {0} failed with exception {1}", OperationId, e.Message));
throw;
}
}
}
}

View File

@@ -51,7 +51,8 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
serviceHost.SetRequestHandler(SchemaCompareRequest.Type, this.HandleSchemaCompareRequest);
serviceHost.SetRequestHandler(SchemaCompareCancellationRequest.Type, this.HandleSchemaCompareCancelRequest);
serviceHost.SetRequestHandler(SchemaCompareGenerateScriptRequest.Type, this.HandleSchemaCompareGenerateScriptRequest);
serviceHost.SetRequestHandler(SchemaComparePublishChangesRequest.Type, this.HandleSchemaComparePublishChangesRequest);
serviceHost.SetRequestHandler(SchemaComparePublishDatabaseChangesRequest.Type, this.HandleSchemaComparePublishDatabaseChangesRequest);
serviceHost.SetRequestHandler(SchemaComparePublishProjectChangesRequest.Type, this.HandleSchemaComparePublishProjectChangesRequest);
serviceHost.SetRequestHandler(SchemaCompareIncludeExcludeNodeRequest.Type, this.HandleSchemaCompareIncludeExcludeNodeRequest);
serviceHost.SetRequestHandler(SchemaCompareGetDefaultOptionsRequest.Type, this.HandleSchemaCompareGetDefaultOptionsRequest);
serviceHost.SetRequestHandler(SchemaCompareOpenScmpRequest.Type, this.HandleSchemaCompareOpenScmpRequest);
@@ -195,16 +196,16 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
}
/// <summary>
/// Handles request for schema compare publish changes script
/// Handles request for schema compare publish database changes script
/// </summary>
/// <returns></returns>
public async Task HandleSchemaComparePublishChangesRequest(SchemaComparePublishChangesParams parameters, RequestContext<ResultStatus> requestContext)
public async Task HandleSchemaComparePublishDatabaseChangesRequest(SchemaComparePublishDatabaseChangesParams parameters, RequestContext<ResultStatus> requestContext)
{
SchemaComparePublishChangesOperation operation = null;
SchemaComparePublishDatabaseChangesOperation operation = null;
try
{
SchemaComparisonResult compareResult = schemaCompareResults.Value[parameters.OperationId];
operation = new SchemaComparePublishChangesOperation(parameters, compareResult);
operation = new SchemaComparePublishDatabaseChangesOperation(parameters, compareResult);
SqlTask sqlTask = null;
TaskMetadata metadata = new TaskMetadata();
metadata.TaskOperation = operation;
@@ -222,7 +223,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
}
catch (Exception e)
{
Logger.Write(TraceEventType.Error, "Failed to publish schema compare changes. Error: " + e);
Logger.Write(TraceEventType.Error, "Failed to publish schema compare database changes. Error: " + e);
await requestContext.SendResult(new ResultStatus()
{
Success = false,
@@ -231,6 +232,51 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
}
}
/// <summary>
/// Handles request for schema compare publish database changes script
/// </summary>
/// <returns></returns>
public async Task HandleSchemaComparePublishProjectChangesRequest(SchemaComparePublishProjectChangesParams parameters, RequestContext<SchemaComparePublishProjectResult> requestContext)
{
SchemaComparePublishProjectChangesOperation operation = null;
try
{
SchemaComparisonResult compareResult = schemaCompareResults.Value[parameters.OperationId];
operation = new SchemaComparePublishProjectChangesOperation(parameters, compareResult);
TaskMetadata metadata = new()
{
TaskOperation = operation,
TargetLocation = parameters.TargetProjectPath,
Name = SR.PublishChangesTaskName
};
SqlTask sqlTask = SqlTaskManagerInstance.CreateTask<SqlTask>(metadata);
await sqlTask.RunAsync();
await requestContext.SendResult(new SchemaComparePublishProjectResult()
{
ChangedFiles = operation.PublishResult.ChangedFiles,
AddedFiles = operation.PublishResult.AddedFiles,
DeletedFiles = operation.PublishResult.DeletedFiles,
Success = true,
ErrorMessage = operation.ErrorMessage
});
}
catch (Exception e)
{
Logger.Write(TraceEventType.Error, "Failed to publish schema compare database changes. Error: " + e);
await requestContext.SendResult(new SchemaComparePublishProjectResult()
{
ChangedFiles = Array.Empty<string>(),
AddedFiles = Array.Empty<string>(),
DeletedFiles = Array.Empty<string>(),
Success = false,
ErrorMessage = operation?.ErrorMessage ?? e.Message
});
}
}
/// <summary>
/// Handles request for exclude incude node in Schema compare result
/// </summary>

View File

@@ -114,6 +114,10 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
{
switch (endpointInfo.EndpointType)
{
case SchemaCompareEndpointType.Project:
{
return new SchemaCompareProjectEndpoint(endpointInfo.ProjectFilePath, endpointInfo.TargetScripts, endpointInfo.DataSchemaProvider);
}
case SchemaCompareEndpointType.Dacpac:
{
return new SchemaCompareDacpacEndpoint(endpointInfo.PackageFilePath);

View File

@@ -19,6 +19,8 @@ using System.Linq;
using System.Threading.Tasks;
using NUnit.Framework;
using System.Diagnostics;
using static Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility.LiveConnectionHelper;
using System.Collections.Generic;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SchemaCompare
{
@@ -122,7 +124,7 @@ WITH VALUES
}
/// <summary>
/// Verify the schema compare request comparing a two databases
/// Verify the schema compare request comparing two databases
/// </summary>
[Test]
public async Task SchemaCompareDatabaseToDatabase()
@@ -160,6 +162,55 @@ WITH VALUES
}
}
/// <summary>
/// Verify the schema compare request comparing two projects
/// </summary>
[Test]
public async Task SchemaCompareProjectToProject()
{
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
try
{
string sourceProjectPath = SchemaCompareTestUtils.CreateProject(sourceDb, "SourceProject");
string targetProjectPath = SchemaCompareTestUtils.CreateProject(targetDb, "TargetProject");
string[] sourceScripts = SchemaCompareTestUtils.GetProjectScripts(sourceProjectPath);
string[] targetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Project;
sourceInfo.ProjectFilePath = Path.Combine(sourceProjectPath, "SourceProject.sqlproj");
sourceInfo.TargetScripts = sourceScripts;
sourceInfo.DataSchemaProvider = "150";
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Project;
targetInfo.ProjectFilePath = Path.Combine(targetProjectPath, "TargetProject.sqlproj");
targetInfo.TargetScripts = targetScripts;
targetInfo.DataSchemaProvider = "150";
var schemaCompareParams = new SchemaCompareParams
{
SourceEndpointInfo = sourceInfo,
TargetEndpointInfo = targetInfo
};
SchemaCompareOperation schemaCompareOperation = new(schemaCompareParams, null, null);
ValidateSchemaCompareWithExcludeIncludeResults(schemaCompareOperation);
// cleanup
SchemaCompareTestUtils.VerifyAndCleanup(sourceProjectPath);
SchemaCompareTestUtils.VerifyAndCleanup(targetProjectPath);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare request comparing a database to a dacpac
/// </summary>
@@ -201,6 +252,97 @@ WITH VALUES
}
}
/// <summary>
/// Verify the schema compare request comparing a database and a project
/// </summary>
[Test]
public async Task SchemaCompareDatabaseToProject()
{
TestConnectionResult result = SchemaCompareTestUtils.GetLiveAutoCompleteTestObjects();
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
try
{
string targetProjectPath = SchemaCompareTestUtils.CreateProject(targetDb, "TargetProject");
string[] targetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Database;
sourceInfo.DatabaseName = sourceDb.DatabaseName;
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Project;
targetInfo.ProjectFilePath = Path.Combine(targetProjectPath, "TargetProject.sqlproj");
targetInfo.TargetScripts = targetScripts;
targetInfo.DataSchemaProvider = "150";
var schemaCompareParams = new SchemaCompareParams
{
SourceEndpointInfo = sourceInfo,
TargetEndpointInfo = targetInfo
};
SchemaCompareOperation schemaCompareOperation = new(schemaCompareParams, result.ConnectionInfo, null);
ValidateSchemaCompareWithExcludeIncludeResults(schemaCompareOperation);
// cleanup
SchemaCompareTestUtils.VerifyAndCleanup(targetProjectPath);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare request comparing a dacpac and a project
/// </summary>
[Test]
public async Task SchemaCompareDacpacToProject()
{
// create dacpacs from databases
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
try
{
string sourceDacpacFilePath = SchemaCompareTestUtils.CreateDacpac(sourceDb);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
sourceInfo.PackageFilePath = sourceDacpacFilePath;
string targetProjectPath = SchemaCompareTestUtils.CreateProject(targetDb, "TargetProject");
string[] targetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Project;
targetInfo.ProjectFilePath = Path.Combine(targetProjectPath, "TargetProject.sqlproj");
targetInfo.TargetScripts = targetScripts;
targetInfo.DataSchemaProvider = "150";
var schemaCompareParams = new SchemaCompareParams
{
SourceEndpointInfo = sourceInfo,
TargetEndpointInfo = targetInfo
};
SchemaCompareOperation schemaCompareOperation = new(schemaCompareParams, null, null);
ValidateSchemaCompareWithExcludeIncludeResults(schemaCompareOperation);
// cleanup
SchemaCompareTestUtils.VerifyAndCleanup(sourceDacpacFilePath);
SchemaCompareTestUtils.VerifyAndCleanup(targetProjectPath);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare generate script request comparing a database to a database
/// </summary>
@@ -299,6 +441,59 @@ WITH VALUES
}
}
/// <summary>
/// Verify the schema compare generate script request comparing a project to a database
/// </summary>
[Test]
public async Task SchemaCompareGenerateScriptProjectToDatabase()
{
TestConnectionResult result = SchemaCompareTestUtils.GetLiveAutoCompleteTestObjects();
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
try
{
string sourceProjectPath = SchemaCompareTestUtils.CreateProject(sourceDb, "SourceProject");
string[] sourceScripts = SchemaCompareTestUtils.GetProjectScripts(sourceProjectPath);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Project;
sourceInfo.ProjectFilePath = Path.Combine(sourceProjectPath, "SourceProject.sqlproj");
sourceInfo.TargetScripts = sourceScripts;
sourceInfo.DataSchemaProvider = "150";
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Database;
targetInfo.DatabaseName = targetDb.DatabaseName;
var schemaCompareParams = new SchemaCompareParams
{
SourceEndpointInfo = sourceInfo,
TargetEndpointInfo = targetInfo
};
SchemaCompareOperation schemaCompareOperation = new(schemaCompareParams, result.ConnectionInfo, result.ConnectionInfo);
// generate script
var generateScriptParams = new SchemaCompareGenerateScriptParams
{
TargetDatabaseName = targetDb.DatabaseName,
OperationId = schemaCompareOperation.OperationId,
};
ValidateSchemaCompareScriptGenerationWithExcludeIncludeResults(schemaCompareOperation, generateScriptParams);
// cleanup
SchemaCompareTestUtils.VerifyAndCleanup(sourceProjectPath);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare publish changes request comparing a dacpac to a database
/// </summary>
@@ -342,13 +537,13 @@ WITH VALUES
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table2]"));
// update target
var publishChangesParams = new SchemaComparePublishChangesParams
var publishChangesParams = new SchemaComparePublishDatabaseChangesParams
{
TargetDatabaseName = targetDb.DatabaseName,
OperationId = schemaCompareOperation.OperationId,
};
SchemaComparePublishChangesOperation publishChangesOperation = new SchemaComparePublishChangesOperation(publishChangesParams, schemaCompareOperation.ComparisonResult);
SchemaComparePublishDatabaseChangesOperation publishChangesOperation = new SchemaComparePublishDatabaseChangesOperation(publishChangesParams, schemaCompareOperation.ComparisonResult);
publishChangesOperation.Execute(TaskExecutionMode.Execute);
Assert.True(publishChangesOperation.PublishResult.Success);
Assert.That(publishChangesOperation.PublishResult.Errors, Is.Empty);
@@ -370,6 +565,80 @@ WITH VALUES
}
}
/// <summary>
/// Verify the schema compare publish changes request comparing a project to a database
/// </summary>
[Test]
public async Task SchemaComparePublishChangesProjectToDatabase()
{
TestConnectionResult result = SchemaCompareTestUtils.GetLiveAutoCompleteTestObjects();
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, null, "SchemaCompareTarget");
try
{
string sourceProjectPath = SchemaCompareTestUtils.CreateProject(sourceDb, "SourceProject");
string[] sourceScripts = SchemaCompareTestUtils.GetProjectScripts(sourceProjectPath);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Project;
sourceInfo.ProjectFilePath = Path.Combine(sourceProjectPath, "SourceProject.sqlproj");
sourceInfo.TargetScripts = sourceScripts;
sourceInfo.DataSchemaProvider = "150";
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Database;
targetInfo.DatabaseName = targetDb.DatabaseName;
SchemaCompareParams schemaCompareParams = new()
{
SourceEndpointInfo = sourceInfo,
TargetEndpointInfo = targetInfo
};
SchemaCompareOperation schemaCompareOperation = new(schemaCompareParams, result.ConnectionInfo, result.ConnectionInfo);
schemaCompareOperation.Execute(TaskExecutionMode.Execute);
Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
IEnumerator<SchemaDifference> enumerator = schemaCompareOperation.ComparisonResult.Differences.GetEnumerator();
enumerator.MoveNext();
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table1]"));
enumerator.MoveNext();
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table2]"));
// update target
SchemaComparePublishDatabaseChangesParams publishChangesParams = new()
{
TargetDatabaseName = targetDb.DatabaseName,
OperationId = schemaCompareOperation.OperationId,
};
SchemaComparePublishDatabaseChangesOperation publishChangesOperation = new(publishChangesParams, schemaCompareOperation.ComparisonResult);
publishChangesOperation.Execute(TaskExecutionMode.Execute);
Assert.True(publishChangesOperation.PublishResult.Success);
Assert.That(publishChangesOperation.PublishResult.Errors, Is.Empty);
// Verify that there are no differences after the publish by running the comparison again
schemaCompareOperation.Execute(TaskExecutionMode.Execute);
Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
Assert.True(schemaCompareOperation.ComparisonResult.IsEqual);
Assert.That(schemaCompareOperation.ComparisonResult.Differences, Is.Empty);
// cleanup
SchemaCompareTestUtils.VerifyAndCleanup(sourceProjectPath);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare publish changes request comparing a database to a database
/// </summary>
@@ -411,13 +680,13 @@ WITH VALUES
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table2]"));
// update target
var publishChangesParams = new SchemaComparePublishChangesParams
var publishChangesParams = new SchemaComparePublishDatabaseChangesParams
{
TargetDatabaseName = targetDb.DatabaseName,
OperationId = schemaCompareOperation.OperationId,
};
SchemaComparePublishChangesOperation publishChangesOperation = new SchemaComparePublishChangesOperation(publishChangesParams, schemaCompareOperation.ComparisonResult);
SchemaComparePublishDatabaseChangesOperation publishChangesOperation = new SchemaComparePublishDatabaseChangesOperation(publishChangesParams, schemaCompareOperation.ComparisonResult);
publishChangesOperation.Execute(TaskExecutionMode.Execute);
Assert.True(publishChangesOperation.PublishResult.Success);
Assert.That(publishChangesOperation.PublishResult.Errors, Is.Empty);
@@ -437,6 +706,260 @@ WITH VALUES
}
}
/// <summary>
/// Verify the schema compare publish changes request comparing a dacpac to a project
/// </summary>
[Test]
public async Task SchemaComparePublishChangesDacpacToProject()
{
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, null, "SchemaCompareTarget");
string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SchemaCompareTest");
Directory.CreateDirectory(folderPath);
try
{
string sourceDacpacFilePath = SchemaCompareTestUtils.CreateDacpac(sourceDb);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
sourceInfo.PackageFilePath = sourceDacpacFilePath;
string targetProjectPath = SchemaCompareTestUtils.CreateProject(targetDb, "TargetProject");
string[] targetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Project;
targetInfo.ProjectFilePath = Path.Combine(targetProjectPath, "TargetProject.sqlproj");
targetInfo.TargetScripts = targetScripts;
targetInfo.DataSchemaProvider = "150";
SchemaCompareParams schemaCompareParams = new()
{
SourceEndpointInfo = sourceInfo,
TargetEndpointInfo = targetInfo
};
SchemaCompareOperation schemaCompareOperation = new(schemaCompareParams, null, null);
schemaCompareOperation.Execute(TaskExecutionMode.Execute);
(schemaCompareOperation.ComparisonResult.Differences as List<SchemaDifference>).RemoveAll(d => !d.Included);
Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
IEnumerator<SchemaDifference> enumerator = schemaCompareOperation.ComparisonResult.Differences.GetEnumerator();
enumerator.MoveNext();
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table1]"));
enumerator.MoveNext();
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table2]"));
// update target
SchemaComparePublishProjectChangesParams publishChangesParams = new()
{
OperationId = schemaCompareOperation.OperationId,
TargetProjectPath = targetProjectPath,
TargetFolderStructure = SqlServer.Dac.DacExtractTarget.Flat,
};
SchemaComparePublishProjectChangesOperation publishChangesOperation = new(publishChangesParams, schemaCompareOperation.ComparisonResult);
publishChangesOperation.Execute(TaskExecutionMode.Execute);
Assert.True(publishChangesOperation.PublishResult.Success);
Assert.AreEqual(publishChangesOperation.PublishResult.ErrorMessage, "");
Assert.AreEqual(publishChangesOperation.PublishResult.ChangedFiles.Length, 0);
Assert.AreEqual(publishChangesOperation.PublishResult.AddedFiles.Length, 2);
Assert.AreEqual(publishChangesOperation.PublishResult.DeletedFiles.Length, 0);
targetInfo.TargetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
// Verify that there are no differences after the publish by running the comparison again
schemaCompareOperation.Execute(TaskExecutionMode.Execute);
(schemaCompareOperation.ComparisonResult.Differences as List<SchemaDifference>).RemoveAll(d => !d.Included);
Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
Assert.True(schemaCompareOperation.ComparisonResult.IsEqual);
Assert.That(schemaCompareOperation.ComparisonResult.Differences, Is.Empty);
// cleanup
SchemaCompareTestUtils.VerifyAndCleanup(sourceDacpacFilePath);
SchemaCompareTestUtils.VerifyAndCleanup(targetProjectPath);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare publish changes request comparing a database to a project
/// </summary>
[Test]
public async Task SchemaComparePublishChangesDatabaseToProject()
{
TestConnectionResult result = SchemaCompareTestUtils.GetLiveAutoCompleteTestObjects();
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, null, "SchemaCompareTarget");
try
{
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Database;
sourceInfo.DatabaseName = sourceDb.DatabaseName;
string targetProjectPath = SchemaCompareTestUtils.CreateProject(targetDb, "TargetProject");
string[] targetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Project;
targetInfo.ProjectFilePath = Path.Combine(targetProjectPath, "TargetProject.sqlproj");
targetInfo.TargetScripts = targetScripts;
targetInfo.DataSchemaProvider = "150";
SchemaCompareParams schemaCompareParams = new()
{
SourceEndpointInfo = sourceInfo,
TargetEndpointInfo = targetInfo
};
SchemaCompareOperation schemaCompareOperation = new(schemaCompareParams, result.ConnectionInfo, result.ConnectionInfo);
schemaCompareOperation.Execute(TaskExecutionMode.Execute);
(schemaCompareOperation.ComparisonResult.Differences as List<SchemaDifference>).RemoveAll(d => !d.Included);
Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
IEnumerator<SchemaDifference> enumerator = schemaCompareOperation.ComparisonResult.Differences.GetEnumerator();
enumerator.MoveNext();
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table1]"));
enumerator.MoveNext();
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table2]"));
// update target
SchemaComparePublishProjectChangesParams publishChangesParams = new()
{
OperationId = schemaCompareOperation.OperationId,
TargetProjectPath = targetProjectPath,
TargetFolderStructure = SqlServer.Dac.DacExtractTarget.Flat,
};
SchemaComparePublishProjectChangesOperation publishChangesOperation = new(publishChangesParams, schemaCompareOperation.ComparisonResult);
publishChangesOperation.Execute(TaskExecutionMode.Execute);
Assert.True(publishChangesOperation.PublishResult.Success);
Assert.AreEqual(publishChangesOperation.PublishResult.ErrorMessage, "");
Assert.AreEqual(publishChangesOperation.PublishResult.ChangedFiles.Length, 0);
Assert.AreEqual(publishChangesOperation.PublishResult.AddedFiles.Length, 2);
Assert.AreEqual(publishChangesOperation.PublishResult.DeletedFiles.Length, 0);
targetInfo.TargetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
// Verify that there are no differences after the publish by running the comparison again
schemaCompareOperation.Execute(TaskExecutionMode.Execute);
(schemaCompareOperation.ComparisonResult.Differences as List<SchemaDifference>).RemoveAll(d => !d.Included);
Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
Assert.True(schemaCompareOperation.ComparisonResult.IsEqual);
Assert.That(schemaCompareOperation.ComparisonResult.Differences, Is.Empty);
// cleanup
SchemaCompareTestUtils.VerifyAndCleanup(targetProjectPath);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare publish changes request comparing a project to a project
/// </summary>
[Test]
public async Task SchemaComparePublishChangesProjectToProject()
{
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, null, "SchemaCompareTarget");
try
{
string sourceProjectPath = SchemaCompareTestUtils.CreateProject(sourceDb, "SourceProject");
string[] sourceScripts = SchemaCompareTestUtils.GetProjectScripts(sourceProjectPath);
string targetProjectPath = SchemaCompareTestUtils.CreateProject(targetDb, "TargetProject");
string[] targetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Project;
sourceInfo.ProjectFilePath = Path.Combine(sourceProjectPath, "SourceProject.sqlproj");
sourceInfo.TargetScripts = sourceScripts;
sourceInfo.DataSchemaProvider = "150";
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Project;
targetInfo.ProjectFilePath = Path.Combine(targetProjectPath, "TargetProject.sqlproj");
targetInfo.TargetScripts = targetScripts;
targetInfo.DataSchemaProvider = "150";
SchemaCompareParams schemaCompareParams = new()
{
SourceEndpointInfo = sourceInfo,
TargetEndpointInfo = targetInfo
};
SchemaCompareOperation schemaCompareOperation = new(schemaCompareParams, null, null);
schemaCompareOperation.Execute(TaskExecutionMode.Execute);
(schemaCompareOperation.ComparisonResult.Differences as List<SchemaDifference>).RemoveAll(d => !d.Included);
Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
IEnumerator<SchemaDifference> enumerator = schemaCompareOperation.ComparisonResult.Differences.GetEnumerator();
enumerator.MoveNext();
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table1]"));
enumerator.MoveNext();
Assert.True(enumerator.Current.SourceObject.Name.ToString().Equals("[dbo].[table2]"));
// update target
SchemaComparePublishProjectChangesParams publishChangesParams = new()
{
OperationId = schemaCompareOperation.OperationId,
TargetProjectPath = targetProjectPath,
TargetFolderStructure = SqlServer.Dac.DacExtractTarget.Flat,
};
SchemaComparePublishProjectChangesOperation publishChangesOperation = new(publishChangesParams, schemaCompareOperation.ComparisonResult);
publishChangesOperation.Execute(TaskExecutionMode.Execute);
Assert.True(publishChangesOperation.PublishResult.Success);
Assert.AreEqual(publishChangesOperation.PublishResult.ErrorMessage, "");
Assert.AreEqual(publishChangesOperation.PublishResult.ChangedFiles.Length, 0);
Assert.AreEqual(publishChangesOperation.PublishResult.AddedFiles.Length, 2);
Assert.AreEqual(publishChangesOperation.PublishResult.DeletedFiles.Length, 0);
targetInfo.TargetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
// Verify that there are no differences after the publish by running the comparison again
schemaCompareOperation.Execute(TaskExecutionMode.Execute);
(schemaCompareOperation.ComparisonResult.Differences as List<SchemaDifference>).RemoveAll(d => !d.Included);
Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
Assert.True(schemaCompareOperation.ComparisonResult.IsEqual);
Assert.That(schemaCompareOperation.ComparisonResult.Differences, Is.Empty);
// cleanup
SchemaCompareTestUtils.VerifyAndCleanup(sourceProjectPath);
SchemaCompareTestUtils.VerifyAndCleanup(targetProjectPath);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare Scmp File Save for database endpoints
/// </summary>
@@ -458,7 +981,7 @@ WITH VALUES
targetInfo.EndpointType = SchemaCompareEndpointType.Database;
targetInfo.DatabaseName = targetDb.DatabaseName;
CreateAndValidateScmpFile(sourceInfo, targetInfo, true, true);
CreateAndValidateScmpFile(sourceInfo, targetInfo, SchemaCompareEndpointType.Database, SchemaCompareEndpointType.Database);
}
finally
{
@@ -490,7 +1013,46 @@ WITH VALUES
targetInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
targetInfo.PackageFilePath = targetDacpac;
CreateAndValidateScmpFile(sourceInfo, targetInfo, false, false);
CreateAndValidateScmpFile(sourceInfo, targetInfo, SchemaCompareEndpointType.Dacpac, SchemaCompareEndpointType.Dacpac);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare Scmp File Save for project endpoints
/// </summary>
[Test]
public async Task SchemaCompareSaveScmpFileForProjects()
{
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
try
{
string filePath = SchemaCompareTestUtils.CreateScmpPath();
string sourceProjectPath = SchemaCompareTestUtils.CreateProject(sourceDb, "SourceProject");
string[] sourceScripts = SchemaCompareTestUtils.GetProjectScripts(sourceProjectPath);
string targetProjectPath = SchemaCompareTestUtils.CreateProject(targetDb, "TargetProject");
string[] targetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Project;
sourceInfo.ProjectFilePath = Path.Combine(sourceProjectPath, "SourceProject.sqlproj");
sourceInfo.TargetScripts = sourceScripts;
sourceInfo.DataSchemaProvider = "150";
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Project;
targetInfo.ProjectFilePath = Path.Combine(targetProjectPath, "TargetProject.sqlproj");
targetInfo.TargetScripts = targetScripts;
targetInfo.DataSchemaProvider = "150";
CreateAndValidateScmpFile(sourceInfo, targetInfo, SchemaCompareEndpointType.Project, SchemaCompareEndpointType.Project);
}
finally
{
@@ -521,7 +1083,78 @@ WITH VALUES
targetInfo.EndpointType = SchemaCompareEndpointType.Database;
targetInfo.DatabaseName = targetDb.DatabaseName;
CreateAndValidateScmpFile(sourceInfo, targetInfo, false, true);
CreateAndValidateScmpFile(sourceInfo, targetInfo, SchemaCompareEndpointType.Dacpac, SchemaCompareEndpointType.Database);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare Scmp File Save for project and db endpoints combination
/// </summary>
[Test]
public async Task SchemaCompareSaveScmpFileForProjectToDB()
{
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
try
{
string filePath = SchemaCompareTestUtils.CreateScmpPath();
string sourceProjectPath = SchemaCompareTestUtils.CreateProject(sourceDb, "SourceProject");
string[] sourceScripts = SchemaCompareTestUtils.GetProjectScripts(sourceProjectPath);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Project;
sourceInfo.ProjectFilePath = Path.Combine(sourceProjectPath, "SourceProject.sqlproj");
sourceInfo.TargetScripts = sourceScripts;
sourceInfo.DataSchemaProvider = "150";
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Database;
targetInfo.DatabaseName = targetDb.DatabaseName;
CreateAndValidateScmpFile(sourceInfo, targetInfo, SchemaCompareEndpointType.Project, SchemaCompareEndpointType.Database);
}
finally
{
sourceDb.Cleanup();
targetDb.Cleanup();
}
}
/// <summary>
/// Verify the schema compare Scmp File Save for dacpac and project endpoints combination
/// </summary>
[Test]
public async Task SchemaCompareSaveScmpFileForDacpacToProject()
{
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
try
{
string filePath = SchemaCompareTestUtils.CreateScmpPath();
string sourceDacpac = SchemaCompareTestUtils.CreateDacpac(sourceDb);
string targetProjectPath = SchemaCompareTestUtils.CreateProject(targetDb, "TargetProject");
string[] targetScripts = SchemaCompareTestUtils.GetProjectScripts(targetProjectPath);
SchemaCompareEndpointInfo sourceInfo = new();
sourceInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
sourceInfo.PackageFilePath = sourceDacpac;
SchemaCompareEndpointInfo targetInfo = new();
targetInfo.EndpointType = SchemaCompareEndpointType.Project;
targetInfo.ProjectFilePath = Path.Combine(targetProjectPath, "TargetProject.sqlproj");
targetInfo.TargetScripts = targetScripts;
targetInfo.DataSchemaProvider = "150";
CreateAndValidateScmpFile(sourceInfo, targetInfo, SchemaCompareEndpointType.Dacpac, SchemaCompareEndpointType.Project);
}
finally
{
@@ -548,6 +1181,15 @@ WITH VALUES
await CreateAndOpenScmp(SchemaCompareEndpointType.Dacpac, SchemaCompareEndpointType.Database);
}
/// <summary>
/// Verify opening an scmp comparing a project and database
/// </summary>
[Test]
public async Task SchemaCompareOpenScmpProjectToDatabaseRequest()
{
await CreateAndOpenScmp(SchemaCompareEndpointType.Project, SchemaCompareEndpointType.Database);
}
/// <summary>
/// Verify opening an scmp comparing two dacpacs
/// </summary>
@@ -557,6 +1199,24 @@ WITH VALUES
await CreateAndOpenScmp(SchemaCompareEndpointType.Dacpac, SchemaCompareEndpointType.Dacpac);
}
/// <summary>
/// Verify opening an scmp comparing a project and dacpac
/// </summary>
[Test]
public async Task SchemaCompareOpenScmpProjectToDacpacRequest()
{
await CreateAndOpenScmp(SchemaCompareEndpointType.Project, SchemaCompareEndpointType.Dacpac);
}
/// <summary>
/// Verify opening an scmp comparing two projects
/// </summary>
[Test]
public async Task SchemaCompareOpenScmpProjectToProjectRequest()
{
await CreateAndOpenScmp(SchemaCompareEndpointType.Project, SchemaCompareEndpointType.Project);
}
/// <summary>
/// Verify the schema compare Service Calls ends to end
/// </summary>
@@ -639,14 +1299,14 @@ WITH VALUES
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(targetDb.ConnectionString);
var publishParams = new SchemaComparePublishChangesParams
var publishParams = new SchemaComparePublishDatabaseChangesParams
{
OperationId = operationId,
TargetDatabaseName = targetDb.DatabaseName,
TargetServerName = builder.DataSource,
};
await SchemaCompareService.Instance.HandleSchemaComparePublishChangesRequest(publishParams, publishRequestContext.Object);
await SchemaCompareService.Instance.HandleSchemaComparePublishDatabaseChangesRequest(publishParams, publishRequestContext.Object);
ValidateTask(SR.PublishChangesTaskName);
// Include/Exclude service call
@@ -1086,7 +1746,7 @@ WITH VALUES
try
{
SchemaCompareEndpoint sourceEndpoint = CreateSchemaCompareEndpoint(sourceDb, sourceEndpointType);
SchemaCompareEndpoint targetEndpoint = CreateSchemaCompareEndpoint(targetDb, targetEndpointType);
SchemaCompareEndpoint targetEndpoint = CreateSchemaCompareEndpoint(targetDb, targetEndpointType, targetEndpointType == SchemaCompareEndpointType.Project);
// create a comparison and exclude the first difference
SchemaComparison compare = new SchemaComparison(sourceEndpoint, targetEndpoint);
@@ -1122,11 +1782,30 @@ WITH VALUES
Assert.That(schemaCompareOpenScmpOperation.Result.ExcludedSourceElements, Is.Not.Empty);
Assert.AreEqual(1, schemaCompareOpenScmpOperation.Result.ExcludedSourceElements.Count());
Assert.That(schemaCompareOpenScmpOperation.Result.ExcludedTargetElements, Is.Empty);
Assert.AreEqual(targetDb.DatabaseName, schemaCompareOpenScmpOperation.Result.OriginalTargetName);
if (targetEndpointType == SchemaCompareEndpointType.Project)
{
Assert.AreEqual(Path.GetFileName((targetEndpoint as SchemaCompareProjectEndpoint).ProjectFilePath), schemaCompareOpenScmpOperation.Result.OriginalTargetName);
}
else
{
Assert.AreEqual(targetDb.DatabaseName, schemaCompareOpenScmpOperation.Result.OriginalTargetName);
}
ValidateResultEndpointInfo(sourceEndpoint, schemaCompareOpenScmpOperation.Result.SourceEndpointInfo, sourceDb.ConnectionString);
ValidateResultEndpointInfo(targetEndpoint, schemaCompareOpenScmpOperation.Result.TargetEndpointInfo, targetDb.ConnectionString);
SchemaCompareTestUtils.VerifyAndCleanup(filePath);
if (sourceEndpointType == SchemaCompareEndpointType.Project)
{
SchemaCompareTestUtils.VerifyAndCleanup(Directory.GetParent((sourceEndpoint as SchemaCompareProjectEndpoint).ProjectFilePath).FullName);
}
if (targetEndpointType == SchemaCompareEndpointType.Project)
{
SchemaCompareTestUtils.VerifyAndCleanup(Directory.GetParent((targetEndpoint as SchemaCompareProjectEndpoint).ProjectFilePath).FullName);
}
}
finally
{
@@ -1135,14 +1814,20 @@ WITH VALUES
}
}
private SchemaCompareEndpoint CreateSchemaCompareEndpoint(SqlTestDb db, SchemaCompareEndpointType endpointType)
private SchemaCompareEndpoint CreateSchemaCompareEndpoint(SqlTestDb db, SchemaCompareEndpointType endpointType, bool isProjectTarget = false)
{
if (endpointType == SchemaCompareEndpointType.Dacpac)
{
string dacpacFilePath = SchemaCompareTestUtils.CreateDacpac(db);
return new SchemaCompareDacpacEndpoint(dacpacFilePath);
}
else
else if (endpointType == SchemaCompareEndpointType.Project)
{
string projectPath = SchemaCompareTestUtils.CreateProject(db, isProjectTarget ? "TargetProject" : "SourceProject");
string[] scripts = SchemaCompareTestUtils.GetProjectScripts(projectPath);
return new SchemaCompareProjectEndpoint(Path.Combine(projectPath, isProjectTarget ? "TargetProject.sqlproj" : "SourceProject.sqlproj"), scripts, "150");
}
else
{
return new SchemaCompareDatabaseEndpoint(db.ConnectionString);
}
@@ -1155,6 +1840,11 @@ WITH VALUES
SchemaCompareDacpacEndpoint dacpacEndpoint = originalEndpoint as SchemaCompareDacpacEndpoint;
Assert.AreEqual(dacpacEndpoint.FilePath, resultEndpoint.PackageFilePath);
}
else if (resultEndpoint.EndpointType == SchemaCompareEndpointType.Project)
{
SchemaCompareProjectEndpoint projectEndpoint = originalEndpoint as SchemaCompareProjectEndpoint;
Assert.AreEqual(projectEndpoint.ProjectFilePath, resultEndpoint.ProjectFilePath);
}
else
{
SchemaCompareDatabaseEndpoint databaseEndpoint = originalEndpoint as SchemaCompareDatabaseEndpoint;
@@ -1193,7 +1883,7 @@ WITH VALUES
Assert.AreEqual(dacFxType, diffObjectTypeType);
}
private void CreateAndValidateScmpFile(SchemaCompareEndpointInfo sourceInfo, SchemaCompareEndpointInfo targetInfo, bool isSourceDb, bool isTargetDb)
private void CreateAndValidateScmpFile(SchemaCompareEndpointInfo sourceInfo, SchemaCompareEndpointInfo targetInfo, SchemaCompareEndpointType sourceType, SchemaCompareEndpointType targetType)
{
string filePath = SchemaCompareTestUtils.CreateScmpPath();
var result = SchemaCompareTestUtils.GetLiveAutoCompleteTestObjects();
@@ -1236,29 +1926,41 @@ WITH VALUES
// Validate with DacFx SchemaComparison object
SchemaComparison sc = new SchemaComparison(filePath);
if (isSourceDb)
if (sourceType == SchemaCompareEndpointType.Database)
{
Assert.True(sc.Source is SchemaCompareDatabaseEndpoint, "Source should be SchemaCompareDatabaseEndpoint");
Assert.True((sc.Source as SchemaCompareDatabaseEndpoint).DatabaseName == sourceInfo.DatabaseName, $"Source Database {(sc.Source as SchemaCompareDatabaseEndpoint).DatabaseName} name does not match the params passed {sourceInfo.DatabaseName}");
}
else
}
else if (sourceType == SchemaCompareEndpointType.Dacpac)
{
Assert.True(sc.Source is SchemaCompareDacpacEndpoint, "Source should be SchemaCompareDacpacEndpoint");
Assert.True((sc.Source as SchemaCompareDacpacEndpoint).FilePath == sourceInfo.PackageFilePath, $"Source dacpac {(sc.Source as SchemaCompareDacpacEndpoint).FilePath} name does not match the params passed {sourceInfo.PackageFilePath}");
SchemaCompareTestUtils.VerifyAndCleanup(sourceInfo.PackageFilePath);
}
if (isTargetDb)
else if (sourceType == SchemaCompareEndpointType.Project)
{
Assert.True(sc.Target is SchemaCompareDatabaseEndpoint, "Source should be SchemaCompareDatabaseEndpoint");
Assert.True((sc.Target as SchemaCompareDatabaseEndpoint).DatabaseName == targetInfo.DatabaseName, $"Source Database {(sc.Target as SchemaCompareDatabaseEndpoint).DatabaseName} name does not match the params passed {targetInfo.DatabaseName}");
Assert.True(sc.Source is SchemaCompareProjectEndpoint, "Source should be SchemaCompareProjectEndpoint");
Assert.True((sc.Source as SchemaCompareProjectEndpoint).ProjectFilePath == sourceInfo.ProjectFilePath, $"Source project {(sc.Source as SchemaCompareProjectEndpoint).ProjectFilePath} name does not match the params passed {sourceInfo.ProjectFilePath}");
SchemaCompareTestUtils.VerifyAndCleanup(Directory.GetParent(sourceInfo.ProjectFilePath).FullName);
}
else
if (targetType == SchemaCompareEndpointType.Database)
{
Assert.True(sc.Target is SchemaCompareDacpacEndpoint, "Source should be SchemaCompareDacpacEndpoint");
Assert.True((sc.Target as SchemaCompareDacpacEndpoint).FilePath == targetInfo.PackageFilePath, $"Source dacpac {(sc.Target as SchemaCompareDacpacEndpoint).FilePath} name does not match the params passed {targetInfo.PackageFilePath}");
Assert.True(sc.Target is SchemaCompareDatabaseEndpoint, "Target should be SchemaCompareDatabaseEndpoint");
Assert.True((sc.Target as SchemaCompareDatabaseEndpoint).DatabaseName == targetInfo.DatabaseName, $"Target Database {(sc.Target as SchemaCompareDatabaseEndpoint).DatabaseName} name does not match the params passed {targetInfo.DatabaseName}");
}
else if (targetType == SchemaCompareEndpointType.Dacpac)
{
Assert.True(sc.Target is SchemaCompareDacpacEndpoint, "Target should be SchemaCompareDacpacEndpoint");
Assert.True((sc.Target as SchemaCompareDacpacEndpoint).FilePath == targetInfo.PackageFilePath, $"Target dacpac {(sc.Target as SchemaCompareDacpacEndpoint).FilePath} name does not match the params passed {targetInfo.PackageFilePath}");
SchemaCompareTestUtils.VerifyAndCleanup(targetInfo.PackageFilePath);
}
else if (targetType == SchemaCompareEndpointType.Project)
{
Assert.True(sc.Target is SchemaCompareProjectEndpoint, "Target should be SchemaCompareProjectEndpoint");
Assert.True((sc.Target as SchemaCompareProjectEndpoint).ProjectFilePath == targetInfo.ProjectFilePath, $"Target project {(sc.Target as SchemaCompareProjectEndpoint).ProjectFilePath} name does not match the params passed {targetInfo.ProjectFilePath}");
SchemaCompareTestUtils.VerifyAndCleanup(Directory.GetParent(targetInfo.ProjectFilePath).FullName);
}
Assert.True(!sc.ExcludedTargetObjects.Any(), "Target Excluded Objects are expected to be Empty");
Assert.True(sc.ExcludedSourceObjects.Count == 1, $"Exactly {1} Source Excluded Object Should be present but {sc.ExcludedSourceObjects.Count} found");

View File

@@ -14,27 +14,34 @@ using NUnit.Framework;
using System;
using System.IO;
using static Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility.LiveConnectionHelper;
using System.Collections.Generic;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SchemaCompare
{
internal static class SchemaCompareTestUtils
{
internal static void VerifyAndCleanup(string filePath)
internal static void VerifyAndCleanup(string path)
{
// Verify it was created
Assert.True(File.Exists(filePath), $"File {filePath} was expected to exist but did not");
// verify it was created...
Assert.True(File.Exists(path) || Directory.Exists(path), $"File or directory {path} was expected to exist but did not");
// Remove the file
if (File.Exists(filePath))
FileAttributes attr = File.GetAttributes(path);
// ...then clean it up
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
{
File.Delete(filePath);
new DirectoryInfo(path).Delete(recursive: true);
}
else
{
File.Delete(path);
}
}
internal static string CreateDacpac(SqlTestDb testdb)
{
var result = GetLiveAutoCompleteTestObjects();
string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SchemaCompareTest");
string folderPath = Path.Combine(Path.GetTempPath(), "SchemaCompareTest");
Directory.CreateDirectory(folderPath);
var extractParams = new ExtractParams
@@ -52,6 +59,34 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SchemaCompare
return extractParams.PackageFilePath;
}
internal static string CreateProject(SqlTestDb testdb, string projectName)
{
var result = GetLiveAutoCompleteTestObjects();
string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SchemaCompareTest", projectName);
Directory.CreateDirectory(folderPath);
File.Create(Path.Combine(folderPath, projectName + ".sqlproj")).Close();
var extractParams = new ExtractParams
{
DatabaseName = testdb.DatabaseName,
ExtractTarget = DacExtractTarget.Flat,
PackageFilePath = folderPath,
ApplicationName = "test",
ApplicationVersion = "1.0.0.0"
};
DacFxService service = new();
ExtractOperation operation = new(extractParams, result.ConnectionInfo);
service.PerformOperation(operation, TaskExecutionMode.Execute);
return folderPath;
}
internal static string[] GetProjectScripts(string projectPath)
{
return Directory.GetFiles(projectPath, "*.sql", SearchOption.AllDirectories);
}
internal static string CreateScmpPath()
{
var result = GetLiveAutoCompleteTestObjects();