diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs index 1bbce090..10b2d9b1 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs @@ -183,7 +183,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution resultSets.Add(resultSet); // Read until we hit the end of the result set - await resultSet.ReadResultToEnd(cancellationToken); + await resultSet.ReadResultToEnd(cancellationToken).ConfigureAwait(false); // Add a message for the number of rows the query returned resultMessages.Add(new ResultMessage(SR.QueryServiceAffectedRows(resultSet.RowCount))); @@ -268,15 +268,23 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution SqlException se = dbe as SqlException; if (se != null) { - foreach (var error in se.Errors) + var errors = se.Errors.Cast().ToList(); + // Detect user cancellation errors + if (errors.Any(error => error.Class == 11 && error.Number == 0)) { - SqlError sqlError = error as SqlError; - if (sqlError != null) + // User cancellation error, add the single message + HasError = false; + resultMessages.Add(new ResultMessage(SR.QueryServiceQueryCancelled)); + } + else + { + // Not a user cancellation error, add all + foreach (var error in errors) { - int lineNumber = sqlError.LineNumber + Selection.StartLine; + int lineNumber = error.LineNumber + Selection.StartLine; string message = string.Format("Msg {0}, Level {1}, State {2}, Line {3}{4}{5}", - sqlError.Number, sqlError.Class, sqlError.State, lineNumber, - Environment.NewLine, sqlError.Message); + error.Number, error.Class, error.State, lineNumber, + Environment.NewLine, error.Message); resultMessages.Add(new ResultMessage(message)); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs index e6abce65..39543c33 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/QueryExecutionService.cs @@ -231,21 +231,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution return; } - // Cancel the query + // Cancel the query and send a success message result.Cancel(); - result.Dispose(); - - // Attempt to dispose the query - if (!ActiveQueries.TryRemove(cancelParams.OwnerUri, out result)) - { - // It really shouldn't be possible to get to this scenario, but we'll cover it anyhow - await requestContext.SendResult(new QueryCancelResult - { - Messages = SR.QueryServiceCancelDisposeFailed - }); - return; - } - await requestContext.SendResult(new QueryCancelResult()); } catch (InvalidOperationException e) diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/ResultSet.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/ResultSet.cs index 39aabd49..cc6a98ab 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/ResultSet.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/ResultSet.cs @@ -201,6 +201,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution /// Cancellation token for cancelling the query public async Task ReadResultToEnd(CancellationToken cancellationToken) { + // Mark that result has been read + hasBeenRead = true; + fileStreamReader = fileStreamFactory.GetReader(outputFileName); + // Open a writer for the file using (IFileStreamWriter fileWriter = fileStreamFactory.GetWriter(outputFileName, MaxCharsToStore, MaxXmlCharsToStore)) { @@ -221,10 +225,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution } // Check if resultset is 'for xml/json'. If it is, set isJson/isXml value in column metadata SingleColumnXmlJsonResultSet(); - - // Mark that result has been read - hasBeenRead = true; - fileStreamReader = fileStreamFactory.GetReader(outputFileName); } #endregion