// // 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; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts; using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.TaskServices; using System; using System.Collections.Concurrent; using System.Threading.Tasks; using Microsoft.SqlTools.ServiceLayer.SchemaCompare; using Microsoft.SqlServer.Dac.Compare; using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.SchemaCopmare { /// /// Main class for SchemaCompare service /// 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 /// public static SchemaCompareService Instance { get { return instance.Value; } } /// /// Initializes the service instance /// /// public void InitializeService(ServiceHost serviceHost) { serviceHost.SetRequestHandler(SchemaCompareRequest.Type, this.HandleSchemaCompareRequest); serviceHost.SetRequestHandler(SchemaCompareGenerateScriptRequest.Type, this.HandleSchemaCompareGenerateScriptRequest); serviceHost.SetRequestHandler(SchemaComparePublishChangesRequest.Type, this.HandleSchemaComparePublishChangesRequest); } /// /// Handles schema compare request /// /// public async Task HandleSchemaCompareRequest(SchemaCompareParams parameters, RequestContext requestContext) { try { ConnectionInfo sourceConnInfo; ConnectionInfo targetConnInfo; ConnectionServiceInstance.TryFindConnection( parameters.SourceEndpointInfo.OwnerUri, out sourceConnInfo); ConnectionServiceInstance.TryFindConnection( parameters.TargetEndpointInfo.OwnerUri, out targetConnInfo); Task schemaCompareTask = Task.Run(async () => { SchemaCompareOperation operation = null; try { 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, Success = true, ErrorMessage = operation.ErrorMessage, AreEqual = operation.ComparisonResult.IsEqual, Differences = operation.Differences }); } catch(Exception e) { await requestContext.SendResult(new SchemaCompareResult() { OperationId = operation != null ? operation.OperationId : null, Success = false, ErrorMessage = operation == null ? e.Message : operation.ErrorMessage, }); } }); } catch (Exception e) { await requestContext.SendError(e); } } /// /// 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 = SR.GenerateScriptTaskName; sqlTask = SqlTaskManagerInstance.CreateAndRun(metadata); await requestContext.SendResult(new ResultStatus() { Success = true, ErrorMessage = operation.ErrorMessage }); } catch (Exception e) { await requestContext.SendResult(new ResultStatus() { Success = false, ErrorMessage = operation == null ? e.Message : operation.ErrorMessage, }); } } /// /// Handles request for schema compare publish changes script /// /// public async Task HandleSchemaComparePublishChangesRequest(SchemaComparePublishChangesParams parameters, RequestContext requestContext) { SchemaComparePublishChangesOperation operation = null; try { SchemaComparisonResult compareResult = schemaCompareResults.Value[parameters.OperationId]; operation = new SchemaComparePublishChangesOperation(parameters, compareResult); SqlTask sqlTask = null; TaskMetadata metadata = new TaskMetadata(); metadata.TaskOperation = operation; metadata.ServerName = parameters.TargetServerName; metadata.DatabaseName = parameters.TargetDatabaseName; metadata.Name = SR.PublishChangesTaskName; sqlTask = SqlTaskManagerInstance.CreateAndRun(metadata); await requestContext.SendResult(new ResultStatus() { Success = true, ErrorMessage = operation.ErrorMessage }); } catch (Exception e) { await requestContext.SendResult(new ResultStatus() { Success = false, ErrorMessage = operation == null ? e.Message : operation.ErrorMessage, }); } } private SqlTaskManager SqlTaskManagerInstance { get { if (sqlTaskManagerInstance == null) { sqlTaskManagerInstance = SqlTaskManager.Instance; } return sqlTaskManagerInstance; } set { sqlTaskManagerInstance = value; } } internal static ConnectionService ConnectionServiceInstance { get { if (connectionService == null) { connectionService = ConnectionService.Instance; } return connectionService; } set { connectionService = value; } } } }