// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // #nullable disable using Microsoft.SqlServer.Dac; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.TaskServices; using Microsoft.SqlTools.ServiceLayer.Utility; using static Microsoft.SqlTools.Utility.SqlConstants; using Microsoft.SqlTools.Utility; using System; using System.Diagnostics; using System.Threading; namespace Microsoft.SqlTools.ServiceLayer.DacFx { /// /// Base class for DacFx operations /// abstract class DacFxOperation : 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 SqlTask SqlTask { get; set; } protected string ConnectionString { get; private set; } protected DacServices DacServices { get; private set; } protected ConnectionInfo ConnInfo { get; private set; } protected DacFxOperation(ConnectionInfo connInfo) { Validate.IsNotNull("connectionInfo", connInfo); Validate.IsNotNull("connectionDetails", connInfo.ConnectionDetails); this.ConnInfo = connInfo; this.ConnectionString = ConnectionService.BuildConnectionString(connInfo.ConnectionDetails); this.OperationId = Guid.NewGuid().ToString(); } protected CancellationToken CancellationToken { get { return this.cancellation.Token; } } /// /// The error occurred during operation /// public string ErrorMessage { get; } /// /// Cancel operation /// public void Cancel() { if (!this.cancellation.IsCancellationRequested) { Logger.Write(TraceEventType.Verbose, string.Format("Cancel invoked for OperationId {0}", this.OperationId)); this.cancellation.Cancel(); } } /// /// Disposes the operation. /// public void Dispose() { if (!disposed) { this.Cancel(); disposed = true; } } public void Execute(TaskExecutionMode mode) { if (this.CancellationToken.IsCancellationRequested) { throw new OperationCanceledException(this.CancellationToken); } try { // Pass in Azure authentication token if needed this.DacServices = this.ConnInfo.ConnectionDetails.AzureAccountToken != null && this.ConnInfo.ConnectionDetails.AuthenticationType == AzureMFA ? new DacServices(this.ConnectionString, new AccessTokenProvider(this.ConnInfo.ConnectionDetails.AzureAccountToken)) : new DacServices(this.ConnectionString); Execute(); } catch (Exception e) { Logger.Write(TraceEventType.Error, string.Format("DacFx import operation {0} failed with exception {1}", this.OperationId, e)); throw; } } public abstract void Execute(); protected DacDeployOptions GetDefaultDeployOptions() { DacDeployOptions options = new DacDeployOptions { AllowDropBlockingAssemblies = true, AllowIncompatiblePlatform = true, BlockOnPossibleDataLoss = false, DropObjectsNotInSource = true, DropPermissionsNotInSource = true, DropRoleMembersNotInSource = true, IgnoreKeywordCasing = false, IgnoreSemicolonBetweenStatements = false, IgnoreWhitespace = false, }; return options; } } }