mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-14 09:59:48 -05:00
Add scripting API implemented by the SqlScriptPublishModel (#316)
Update the ScriptingService to expose new scripting JSON-RPC APIs that use the SqlScriptPublishModel for script generation. The SqlScriptPublishModel is the model behind the SSMS scripting wizard. To enable scripting for CLI tools, we've ported SqlScriptPublishModel to .NET Core. The SqlScriptPublishModel wraps the SMO scripting APIs for .sql script generation. 1) Added three new requests to the ScriptingService: ScriptingRequest, ScriptingListObjectsRequest, ScriptingCancelRequest. 2) Generating scripts are long running operations, so the ScriptingRequest and ScriptingListObjectsRequest kick off a long running scripting task and return immediately. 3) Long running scripting task reports progress and completion, and can be cancelled by a ScriptingCancelRequest request. 4) Bumped the SMO nuget package to 140.17049.0. This new version contains a signed SSMS_Rel build of SMO with the SqlScriptPublishModel. 5) For testing, adding the Northwind database schema TODO (in later pull requests) 1) Integrate the new ScriptingService APIs with the ConnectionService 2) Integrate with the metadata support recently added
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Data.SqlClient;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
using Microsoft.SqlServer.Management.SqlScriptPublish;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
{
|
||||
/// <summary>
|
||||
/// Class to represent an in-progress list objects operation.
|
||||
/// </summary>
|
||||
public sealed class ScriptingListObjectsOperation : ScriptingOperation
|
||||
{
|
||||
private bool disposed = false;
|
||||
|
||||
public ScriptingListObjectsOperation(ScriptingListObjectsParams parameters)
|
||||
{
|
||||
Validate.IsNotNull("parameters", parameters);
|
||||
|
||||
this.Parameters = parameters;
|
||||
}
|
||||
|
||||
private ScriptingListObjectsParams Parameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when a the list object operation is complete.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An event can be completed by the following conditions: success, cancel, error.
|
||||
/// </remarks>
|
||||
public event EventHandler<ScriptingListObjectsCompleteParams> CompleteNotification;
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
if (this.CancellationToken.IsCancellationRequested)
|
||||
{
|
||||
throw new OperationCanceledException(this.CancellationToken);
|
||||
}
|
||||
|
||||
SqlScriptPublishModel publishModel = null;
|
||||
|
||||
try
|
||||
{
|
||||
this.ValidateScriptDatabaseParams();
|
||||
|
||||
publishModel = new SqlScriptPublishModel(this.Parameters.ConnectionString);
|
||||
List<ScriptingObject> databaseObjects = publishModel.GetDatabaseObjects();
|
||||
|
||||
Logger.Write(
|
||||
LogLevel.Verbose,
|
||||
string.Format(
|
||||
"Sending list object completion notification count {0}, objects: {1}",
|
||||
databaseObjects,
|
||||
string.Join(", ", databaseObjects)));
|
||||
|
||||
this.SendCompletionNotificationEvent(new ScriptingListObjectsCompleteParams
|
||||
{
|
||||
OperationId = this.OperationId,
|
||||
DatabaseObjects = databaseObjects,
|
||||
Count = databaseObjects.Count,
|
||||
Success = true,
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Write(LogLevel.Normal, string.Format("Scripting operation {0} was canceled", this.OperationId));
|
||||
if (e.IsOperationCanceledException())
|
||||
{
|
||||
this.SendCompletionNotificationEvent(new ScriptingListObjectsCompleteParams
|
||||
{
|
||||
OperationId = this.OperationId,
|
||||
Canceled = true,
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Write(LogLevel.Error, string.Format("Scripting operation {0} failed with exception {1}", this.OperationId, e));
|
||||
this.SendCompletionNotificationEvent(new ScriptingListObjectsCompleteParams
|
||||
{
|
||||
OperationId = this.OperationId,
|
||||
HasError = true,
|
||||
ErrorMessage = e.Message,
|
||||
ErrorDetails = e.ToString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SendCompletionNotificationEvent(ScriptingListObjectsCompleteParams parameters)
|
||||
{
|
||||
this.CompleteNotification?.Invoke(this, parameters);
|
||||
}
|
||||
|
||||
private void ValidateScriptDatabaseParams()
|
||||
{
|
||||
try
|
||||
{
|
||||
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(this.Parameters.ConnectionString);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ArgumentException(SR.ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the scripting operation.
|
||||
/// </summary>
|
||||
public override void Dispose()
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
this.Cancel();
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user