From 0c46c5bfdb86367a982d555677d6f2709df7d521 Mon Sep 17 00:00:00 2001
From: kisantia <31145923+kisantia@users.noreply.github.com>
Date: Fri, 29 Mar 2019 14:12:37 -0700
Subject: [PATCH] Add schema compare generate script operation (#787)
* add generate script operation
---
.../SchemaCompareGenerateScriptRequest.cs | 47 +++
.../SchemaCompareGenerateScriptOperation.cs | 82 +++++
.../SchemaCompare/SchemaCompareOperation.cs | 12 +-
.../SchemaCompare/SchemaCompareService.cs | 76 ++++-
.../SchemaCompareServiceTests.cs | 291 +++++++++++++-----
5 files changed, 423 insertions(+), 85 deletions(-)
create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/Contracts/SchemaCompareGenerateScriptRequest.cs
create mode 100644 src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareGenerateScriptOperation.cs
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/Contracts/SchemaCompareGenerateScriptRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/Contracts/SchemaCompareGenerateScriptRequest.cs
new file mode 100644
index 00000000..f45cec9f
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/Contracts/SchemaCompareGenerateScriptRequest.cs
@@ -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.Compare;
+using Microsoft.SqlTools.Hosting.Protocol.Contracts;
+using Microsoft.SqlTools.ServiceLayer.TaskServices;
+using Microsoft.SqlTools.ServiceLayer.Utility;
+using System.Collections.Generic;
+
+namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts
+{
+ ///
+ /// Parameters for a schema compare generate script request.
+ ///
+ public class SchemaCompareGenerateScriptParams
+ {
+ ///
+ /// Operation id of the schema compare operation
+ ///
+ public string OperationId { get; set; }
+
+ ///
+ /// Name of target database
+ ///
+ public string TargetDatabaseName { get; set; }
+
+ ///
+ /// Gets or sets the filepath where to save the generated script
+ ///
+ public string ScriptFilePath { get; set; }
+
+ ///
+ /// Execution mode for the operation. Default is execution
+ ///
+ public TaskExecutionMode TaskExecutionMode { get; set; }
+ }
+
+ ///
+ /// Defines the Schema Compare generate script request type
+ ///
+ class SchemaCompareGenerateScriptRequest
+ {
+ public static readonly RequestType Type =
+ RequestType.Create("schemaCompare/generateScript");
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareGenerateScriptOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareGenerateScriptOperation.cs
new file mode 100644
index 00000000..ad13ba8c
--- /dev/null
+++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareGenerateScriptOperation.cs
@@ -0,0 +1,82 @@
+//
+// 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.ServiceLayer.Connection;
+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.Threading;
+
+namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
+{
+ ///
+ /// Class to represent an in-progress schema compare generate script operation
+ ///
+ class SchemaCompareGenerateScriptOperation : ITaskOperation
+ {
+ private CancellationTokenSource cancellation = new CancellationTokenSource();
+ private bool disposed = false;
+
+ ///
+ /// Gets the unique id associated with this instance.
+ ///
+ public string OperationId { get; private set; }
+
+ public SchemaCompareGenerateScriptParams 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 SchemaCompareGenerateScriptOperation(SchemaCompareGenerateScriptParams parameters, SchemaComparisonResult comparisonResult)
+ {
+ Validate.IsNotNull("parameters", parameters);
+ Validate.IsNotNull("scriptFilePath", parameters.ScriptFilePath);
+ this.Parameters = parameters;
+ Validate.IsNotNull("comparisonResult", comparisonResult);
+ this.ComparisonResult = comparisonResult;
+ }
+
+ public void Execute(TaskExecutionMode mode)
+ {
+ if (this.CancellationToken.IsCancellationRequested)
+ {
+ throw new OperationCanceledException(this.CancellationToken);
+ }
+
+ try
+ {
+ SchemaCompareScriptGenerationResult result = this.ComparisonResult.GenerateScript(this.Parameters.TargetDatabaseName);
+ File.WriteAllText(this.Parameters.ScriptFilePath, result.Script);
+
+ if (!string.IsNullOrEmpty(result.MasterScript))
+ {
+ // master script is only used if the target is Azure SQL db and the script contains all operations that must be done against the master database
+ string masterScriptPath = Path.Combine(Path.GetDirectoryName(this.Parameters.ScriptFilePath), string.Concat("master_", Path.GetFileName(this.Parameters.ScriptFilePath)));
+ File.WriteAllText(masterScriptPath, result.MasterScript);
+ }
+ }
+ catch (Exception e)
+ {
+ ErrorMessage = e.Message;
+ Logger.Write(TraceEventType.Error, string.Format("Schema compare generate script 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()
+ {
+ }
+ }
+}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs
index 15b37da6..61b043c7 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareOperation.cs
@@ -56,16 +56,9 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
///
public string ErrorMessage { get; set; }
- ///
- /// Cancel operation
- ///
+ // The schema compare public api doesn't currently take a cancellation token so the operation can't be cancelled
public void Cancel()
{
- if (!this.cancellation.IsCancellationRequested)
- {
- Logger.Write(TraceEventType.Verbose, string.Format("Cancel invoked for OperationId {0}", this.OperationId));
- this.cancellation.Cancel();
- }
}
///
@@ -110,7 +103,8 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
}
catch (Exception e)
{
- Logger.Write(TraceEventType.Error, string.Format("Schema compare operation {0} failed with exception {1}", this.OperationId, e));
+ ErrorMessage = e.Message;
+ Logger.Write(TraceEventType.Error, string.Format("Schema compare operation {0} failed with exception {1}", this.OperationId, e.Message));
throw;
}
}
diff --git a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareService.cs b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareService.cs
index d3cfa5af..55220e66 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/SchemaCompare/SchemaCompareService.cs
@@ -9,9 +9,10 @@ using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using System;
using System.Collections.Concurrent;
-using System.Data.SqlClient;
using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare;
+using Microsoft.SqlServer.Dac.Compare;
+using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCopmare
{
@@ -21,7 +22,10 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCopmare
class SchemaCompareService
{
private static ConnectionService connectionService = null;
+ private SqlTaskManager sqlTaskManagerInstance = null;
private static readonly Lazy instance = new Lazy(() => new SchemaCompareService());
+ private Lazy> schemaCompareResults =
+ new Lazy>(() => new ConcurrentDictionary());
///
/// Gets the singleton instance object
@@ -38,6 +42,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCopmare
public void InitializeService(ServiceHost serviceHost)
{
serviceHost.SetRequestHandler(SchemaCompareRequest.Type, this.HandleSchemaCompareRequest);
+ serviceHost.SetRequestHandler(SchemaCompareGenerateScriptRequest.Type, this.HandleSchemaCompareGenerateScriptRequest);
}
///
@@ -59,11 +64,16 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCopmare
Task schemaCompareTask = Task.Run(async () =>
{
+ SchemaCompareOperation operation = null;
+
try
{
- SchemaCompareOperation operation = new SchemaCompareOperation(parameters, sourceConnInfo, targetConnInfo);
+ operation = new SchemaCompareOperation(parameters, sourceConnInfo, targetConnInfo);
operation.Execute(parameters.TaskExecutionMode);
+ // add result to dictionary of results
+ schemaCompareResults.Value[operation.OperationId] = operation.ComparisonResult;
+
await requestContext.SendResult(new SchemaCompareResult()
{
OperationId = operation.OperationId,
@@ -73,9 +83,14 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCopmare
Differences = operation.Differences
});
}
- catch(Exception e)
+ catch
{
- await requestContext.SendError(e);
+ await requestContext.SendResult(new SchemaCompareResult()
+ {
+ OperationId = operation != null ? operation.OperationId : null,
+ Success = false,
+ ErrorMessage = operation.ErrorMessage,
+ });
}
});
}
@@ -85,6 +100,59 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCopmare
}
}
+ ///
+ /// Handles request for schema compare generate deploy script
+ ///
+ ///
+ public async Task HandleSchemaCompareGenerateScriptRequest(SchemaCompareGenerateScriptParams parameters, RequestContext requestContext)
+ {
+ SchemaCompareGenerateScriptOperation operation = null;
+ try
+ {
+ SchemaComparisonResult compareResult = schemaCompareResults.Value[parameters.OperationId];
+ operation = new SchemaCompareGenerateScriptOperation(parameters, compareResult);
+ SqlTask sqlTask = null;
+ TaskMetadata metadata = new TaskMetadata();
+ metadata.TaskOperation = operation;
+ // want to show filepath in task history instead of server and database
+ metadata.ServerName = parameters.ScriptFilePath;
+ metadata.DatabaseName = string.Empty;
+ metadata.Name = "Generate Script";
+
+ sqlTask = SqlTaskManagerInstance.CreateAndRun(metadata);
+
+ await requestContext.SendResult(new ResultStatus()
+ {
+ Success = true,
+ ErrorMessage = operation.ErrorMessage
+ });
+ }
+ catch
+ {
+ await requestContext.SendResult(new ResultStatus()
+ {
+ Success = false,
+ ErrorMessage = operation.ErrorMessage
+ });
+ }
+ }
+
+ private SqlTaskManager SqlTaskManagerInstance
+ {
+ get
+ {
+ if (sqlTaskManagerInstance == null)
+ {
+ sqlTaskManagerInstance = SqlTaskManager.Instance;
+ }
+ return sqlTaskManagerInstance;
+ }
+ set
+ {
+ sqlTaskManagerInstance = value;
+ }
+ }
+
internal static ConnectionService ConnectionServiceInstance
{
get
diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareServiceTests.cs
index 8f3d13c6..cae9dda8 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareServiceTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/SchemaCompare/SchemaCompareServiceTests.cs
@@ -51,6 +51,7 @@ CREATE TABLE [dbo].[table3]
private async Task>> SendAndValidateSchemaCompareRequestDacpacToDacpac()
{
+
var result = GetLiveAutoCompleteTestObjects();
var schemaCompareRequestContext = new Mock>();
schemaCompareRequestContext.Setup(x => x.SendResult(It.IsAny())).Returns(Task.FromResult(new object()));
@@ -58,36 +59,41 @@ CREATE TABLE [dbo].[table3]
// 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");
- string sourceDacpacFilePath = CreateDacpac(sourceDb);
- string targetDacpacFilePath = CreateDacpac(targetDb);
-
- SchemaCompareEndpointInfo sourceInfo = new SchemaCompareEndpointInfo();
- SchemaCompareEndpointInfo targetInfo = new SchemaCompareEndpointInfo();
-
- sourceInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
- sourceInfo.PackageFilePath = sourceDacpacFilePath;
- targetInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
- targetInfo.PackageFilePath = targetDacpacFilePath;
-
- var schemaCompareParams = new SchemaCompareParams
+ try
{
- SourceEndpointInfo = sourceInfo,
- TargetEndpointInfo = targetInfo
- };
+ string sourceDacpacFilePath = CreateDacpac(sourceDb);
+ string targetDacpacFilePath = CreateDacpac(targetDb);
- DacFxService service = new DacFxService();
- SchemaCompareOperation schemaCompareOperation = new SchemaCompareOperation(schemaCompareParams, null, null);
- schemaCompareOperation.Execute(TaskExecutionMode.Execute);
+ SchemaCompareEndpointInfo sourceInfo = new SchemaCompareEndpointInfo();
+ SchemaCompareEndpointInfo targetInfo = new SchemaCompareEndpointInfo();
- Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
- Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
- Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
+ sourceInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
+ sourceInfo.PackageFilePath = sourceDacpacFilePath;
+ targetInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
+ targetInfo.PackageFilePath = targetDacpacFilePath;
- // cleanup
- VerifyAndCleanup(sourceDacpacFilePath);
- VerifyAndCleanup(targetDacpacFilePath);
- sourceDb.Cleanup();
- targetDb.Cleanup();
+ var schemaCompareParams = new SchemaCompareParams
+ {
+ SourceEndpointInfo = sourceInfo,
+ TargetEndpointInfo = targetInfo
+ };
+
+ SchemaCompareOperation schemaCompareOperation = new SchemaCompareOperation(schemaCompareParams, null, null);
+ schemaCompareOperation.Execute(TaskExecutionMode.Execute);
+
+ Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
+ Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
+ Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
+
+ // cleanup
+ VerifyAndCleanup(sourceDacpacFilePath);
+ VerifyAndCleanup(targetDacpacFilePath);
+ }
+ finally
+ {
+ sourceDb.Cleanup();
+ targetDb.Cleanup();
+ }
return schemaCompareRequestContext;
}
@@ -100,35 +106,38 @@ CREATE TABLE [dbo].[table3]
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
- string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DacFxTest");
+ string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SchemaCompareTest");
Directory.CreateDirectory(folderPath);
- SchemaCompareEndpointInfo sourceInfo = new SchemaCompareEndpointInfo();
- SchemaCompareEndpointInfo targetInfo = new SchemaCompareEndpointInfo();
-
- sourceInfo.EndpointType = SchemaCompareEndpointType.Database;
- sourceInfo.DatabaseName = sourceDb.DatabaseName;
- targetInfo.EndpointType = SchemaCompareEndpointType.Database;
- targetInfo.DatabaseName = targetDb.DatabaseName;
-
- var schemaCompareParams = new SchemaCompareParams
+ try
{
- SourceEndpointInfo = sourceInfo,
- TargetEndpointInfo = targetInfo
- };
+ SchemaCompareEndpointInfo sourceInfo = new SchemaCompareEndpointInfo();
+ SchemaCompareEndpointInfo targetInfo = new SchemaCompareEndpointInfo();
- DacFxService service = new DacFxService();
- SchemaCompareOperation schemaCompareOperation = new SchemaCompareOperation(schemaCompareParams, result.ConnectionInfo, result.ConnectionInfo);
- schemaCompareOperation.Execute(TaskExecutionMode.Execute);
+ sourceInfo.EndpointType = SchemaCompareEndpointType.Database;
+ sourceInfo.DatabaseName = sourceDb.DatabaseName;
+ targetInfo.EndpointType = SchemaCompareEndpointType.Database;
+ targetInfo.DatabaseName = targetDb.DatabaseName;
- Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
- Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
- Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
+ var schemaCompareParams = new SchemaCompareParams
+ {
+ SourceEndpointInfo = sourceInfo,
+ TargetEndpointInfo = targetInfo
+ };
- // cleanup
- sourceDb.Cleanup();
- targetDb.Cleanup();
+ SchemaCompareOperation schemaCompareOperation = new SchemaCompareOperation(schemaCompareParams, result.ConnectionInfo, result.ConnectionInfo);
+ schemaCompareOperation.Execute(TaskExecutionMode.Execute);
+ Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
+ Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
+ Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
+ }
+ finally
+ {
+ // cleanup
+ sourceDb.Cleanup();
+ targetDb.Cleanup();
+ }
return schemaCompareRequestContext;
}
@@ -140,35 +149,155 @@ CREATE TABLE [dbo].[table3]
SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
- string targetDacpacFilePath = CreateDacpac(targetDb);
- SchemaCompareEndpointInfo sourceInfo = new SchemaCompareEndpointInfo();
- SchemaCompareEndpointInfo targetInfo = new SchemaCompareEndpointInfo();
-
- sourceInfo.EndpointType = SchemaCompareEndpointType.Database;
- sourceInfo.DatabaseName = sourceDb.DatabaseName;
- targetInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
- targetInfo.PackageFilePath = targetDacpacFilePath;
-
- var schemaCompareParams = new SchemaCompareParams
+ try
{
- SourceEndpointInfo = sourceInfo,
- TargetEndpointInfo = targetInfo
- };
+ string targetDacpacFilePath = CreateDacpac(targetDb);
- DacFxService service = new DacFxService();
- SchemaCompareOperation schemaCompareOperation = new SchemaCompareOperation(schemaCompareParams, result.ConnectionInfo, null);
- schemaCompareOperation.Execute(TaskExecutionMode.Execute);
+ SchemaCompareEndpointInfo sourceInfo = new SchemaCompareEndpointInfo();
+ SchemaCompareEndpointInfo targetInfo = new SchemaCompareEndpointInfo();
- Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
- Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
- Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
+ sourceInfo.EndpointType = SchemaCompareEndpointType.Database;
+ sourceInfo.DatabaseName = sourceDb.DatabaseName;
+ targetInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
+ targetInfo.PackageFilePath = targetDacpacFilePath;
- // cleanup
- VerifyAndCleanup(targetDacpacFilePath);
- sourceDb.Cleanup();
- targetDb.Cleanup();
+ var schemaCompareParams = new SchemaCompareParams
+ {
+ SourceEndpointInfo = sourceInfo,
+ TargetEndpointInfo = targetInfo
+ };
+ SchemaCompareOperation schemaCompareOperation = new SchemaCompareOperation(schemaCompareParams, result.ConnectionInfo, null);
+ schemaCompareOperation.Execute(TaskExecutionMode.Execute);
+
+ Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
+ Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
+ Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
+
+ // cleanup
+ VerifyAndCleanup(targetDacpacFilePath);
+ }
+ finally
+ {
+ sourceDb.Cleanup();
+ targetDb.Cleanup();
+ }
+ return schemaCompareRequestContext;
+ }
+
+ private async Task>> SendAndValidateSchemaCompareGenerateScriptRequestDatabaseToDatabase()
+ {
+ var result = GetLiveAutoCompleteTestObjects();
+ var schemaCompareRequestContext = new Mock>();
+ schemaCompareRequestContext.Setup(x => x.SendResult(It.IsAny())).Returns(Task.FromResult(new object()));
+
+ SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
+ SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
+ string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SchemaCompareTest");
+ Directory.CreateDirectory(folderPath);
+
+ try
+ {
+ SchemaCompareEndpointInfo sourceInfo = new SchemaCompareEndpointInfo();
+ SchemaCompareEndpointInfo targetInfo = new SchemaCompareEndpointInfo();
+
+ sourceInfo.EndpointType = SchemaCompareEndpointType.Database;
+ sourceInfo.DatabaseName = sourceDb.DatabaseName;
+ targetInfo.EndpointType = SchemaCompareEndpointType.Database;
+ targetInfo.DatabaseName = targetDb.DatabaseName;
+
+ var schemaCompareParams = new SchemaCompareParams
+ {
+ SourceEndpointInfo = sourceInfo,
+ TargetEndpointInfo = targetInfo
+ };
+
+ SchemaCompareOperation schemaCompareOperation = new SchemaCompareOperation(schemaCompareParams, result.ConnectionInfo, result.ConnectionInfo);
+ schemaCompareOperation.Execute(TaskExecutionMode.Execute);
+
+ Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
+ Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
+ Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
+
+ // generate script
+ var generateScriptParams = new SchemaCompareGenerateScriptParams
+ {
+ TargetDatabaseName = targetDb.DatabaseName,
+ OperationId = schemaCompareOperation.OperationId,
+ ScriptFilePath = Path.Combine(folderPath, string.Concat(sourceDb.DatabaseName, "_", "Update.publish.sql"))
+ };
+
+ SchemaCompareGenerateScriptOperation generateScriptOperation = new SchemaCompareGenerateScriptOperation(generateScriptParams, schemaCompareOperation.ComparisonResult);
+ generateScriptOperation.Execute(TaskExecutionMode.Execute);
+
+ // cleanup
+ VerifyAndCleanup(generateScriptParams.ScriptFilePath);
+ }
+ finally
+ {
+ sourceDb.Cleanup();
+ targetDb.Cleanup();
+ }
+ return schemaCompareRequestContext;
+ }
+
+ private async Task>> SendAndValidateSchemaCompareGenerateScriptRequestDacpacToDatabase()
+ {
+ var result = GetLiveAutoCompleteTestObjects();
+ var schemaCompareRequestContext = new Mock>();
+ schemaCompareRequestContext.Setup(x => x.SendResult(It.IsAny())).Returns(Task.FromResult(new object()));
+
+ SqlTestDb sourceDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, SourceScript, "SchemaCompareSource");
+ SqlTestDb targetDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, TargetScript, "SchemaCompareTarget");
+ string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SchemaCompareTest");
+ Directory.CreateDirectory(folderPath);
+
+ try
+ {
+ string sourceDacpacFilePath = CreateDacpac(sourceDb);
+
+ SchemaCompareEndpointInfo sourceInfo = new SchemaCompareEndpointInfo();
+ SchemaCompareEndpointInfo targetInfo = new SchemaCompareEndpointInfo();
+
+ sourceInfo.EndpointType = SchemaCompareEndpointType.Dacpac;
+ sourceInfo.PackageFilePath = sourceDacpacFilePath;
+ targetInfo.EndpointType = SchemaCompareEndpointType.Database;
+ targetInfo.DatabaseName = targetDb.DatabaseName;
+
+ var schemaCompareParams = new SchemaCompareParams
+ {
+ SourceEndpointInfo = sourceInfo,
+ TargetEndpointInfo = targetInfo
+ };
+
+ SchemaCompareOperation schemaCompareOperation = new SchemaCompareOperation(schemaCompareParams, result.ConnectionInfo, result.ConnectionInfo);
+ schemaCompareOperation.Execute(TaskExecutionMode.Execute);
+
+ Assert.True(schemaCompareOperation.ComparisonResult.IsValid);
+ Assert.False(schemaCompareOperation.ComparisonResult.IsEqual);
+ Assert.NotNull(schemaCompareOperation.ComparisonResult.Differences);
+
+ // generate script
+ var generateScriptParams = new SchemaCompareGenerateScriptParams
+ {
+ TargetDatabaseName = targetDb.DatabaseName,
+ OperationId = schemaCompareOperation.OperationId,
+ ScriptFilePath = Path.Combine(folderPath, string.Concat(sourceDb.DatabaseName, "_", "Update.publish.sql"))
+ };
+
+ SchemaCompareGenerateScriptOperation generateScriptOperation = new SchemaCompareGenerateScriptOperation(generateScriptParams, schemaCompareOperation.ComparisonResult);
+ generateScriptOperation.Execute(TaskExecutionMode.Execute);
+
+ // cleanup
+ VerifyAndCleanup(generateScriptParams.ScriptFilePath);
+ VerifyAndCleanup(sourceDacpacFilePath);
+ }
+ finally
+ {
+ sourceDb.Cleanup();
+ targetDb.Cleanup();
+ }
return schemaCompareRequestContext;
}
@@ -199,6 +328,24 @@ CREATE TABLE [dbo].[table3]
Assert.NotNull(await SendAndValidateSchemaCompareRequestDatabaseToDacpac());
}
+ ///
+ /// Verify the schema compare generate script request comparing a database to a database
+ ///
+ [Fact]
+ public async void SchemaCompareGenerateScriptDatabaseToDatabase()
+ {
+ Assert.NotNull(await SendAndValidateSchemaCompareGenerateScriptRequestDatabaseToDatabase());
+ }
+
+ ///
+ /// Verify the schema compare generate script request comparing a dacpac to a database
+ ///
+ [Fact]
+ public async void SchemaCompareGenerateScriptDacpacToDatabase()
+ {
+ Assert.NotNull(await SendAndValidateSchemaCompareGenerateScriptRequestDacpacToDatabase());
+ }
+
private void VerifyAndCleanup(string filePath)
{
// Verify it was created
@@ -214,7 +361,7 @@ CREATE TABLE [dbo].[table3]
private string CreateDacpac(SqlTestDb testdb)
{
var result = GetLiveAutoCompleteTestObjects();
- string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "DacFxTest");
+ string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SchemaCompareTest");
Directory.CreateDirectory(folderPath);
var extractParams = new ExtractParams