From d78c1947e09a04c1b10af5fa40bc2cddb3880fae Mon Sep 17 00:00:00 2001 From: Benjamin Russell Date: Fri, 29 Jul 2016 12:52:24 -0700 Subject: [PATCH] Stubbing out connectionservice with guid id --- .../ConnectionServices/ConnectionService.cs | 63 +++++++++++++++---- .../Contracts/ConnectionMessages.cs | 3 +- .../Contracts/ISqlConnection.cs | 9 +-- .../Contracts/SqlConnection.cs | 23 ------- .../LanguageServices/AutoCompleteService.cs | 20 +++++- .../LanguageServices/LanguageService.cs | 3 +- 6 files changed, 74 insertions(+), 47 deletions(-) diff --git a/src/ServiceHost/ConnectionServices/ConnectionService.cs b/src/ServiceHost/ConnectionServices/ConnectionService.cs index 1b62ab50..d7f11fe1 100644 --- a/src/ServiceHost/ConnectionServices/ConnectionService.cs +++ b/src/ServiceHost/ConnectionServices/ConnectionService.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using System.Data; using System.Data.SqlClient; using System.Linq; using System.Threading.Tasks; @@ -55,17 +56,12 @@ namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices /// private ISqlConnectionFactory connectionFactory; - /// - /// The current connection id that was previously used - /// - private int maxConnectionId = 0; - /// /// Active connections lazy dictionary instance /// - private Lazy> activeConnections - = new Lazy>(() - => new Dictionary()); + private Lazy> activeConnections + = new Lazy>(() + => new Dictionary()); /// /// Callback for onconnection handler @@ -81,7 +77,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices /// /// Gets the active connection map /// - public Dictionary ActiveConnections + public Dictionary ActiveConnections { get { @@ -133,7 +129,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices await connection.OpenAsync(); // map the connection id to the connection object for future lookups - ActiveConnections.Add(++maxConnectionId, connection); + Guid connectionId = Guid.NewGuid(); + ActiveConnections.Add(connectionId, connection); // invoke callback notifications var onConnectionCallbackTasks = onConnectionActivities.Select(t => t(connection)); @@ -141,16 +138,35 @@ namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices // TODO: Evaulate if we want to avoid waiting here. We'll need error handling on the other side if we don't wait // return the connection result - return new ConnectionResult() + return new ConnectionResult { - ConnectionId = maxConnectionId + ConnectionId = connectionId }; } + /// + /// Closes an active connection and removes it from the active connections list + /// + /// ID of the connection to close + public void Disconnect(Guid connectionId) + { + if (!ActiveConnections.ContainsKey(connectionId)) + { + // TODO: Should this possibly be a throw condition? + return; + } + + ActiveConnections[connectionId].Close(); + ActiveConnections.Remove(connectionId); + } + public void Initialize(ServiceHost serviceHost) { // Register request and event handlers with the Service Host serviceHost.SetRequestHandler(ConnectionRequest.Type, HandleConnectRequest); + + // Register the shutdown handler + serviceHost.RegisterShutdownTask(HandleShutdownRequest); } /// @@ -162,6 +178,15 @@ namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices onConnectionActivities.Add(activity); } + public ISqlConnection GetConnection(Guid connectionId) + { + if (!ActiveConnections.ContainsKey(connectionId)) + { + throw new ArgumentException("Connection with provided ID could not be found"); + } + return ActiveConnections[connectionId]; + } + #endregion #region Request Handlers @@ -184,6 +209,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices await requestContext.SendResult(result); } + /// + /// Handles shutdown event by closing out any active connections + /// + protected async Task HandleShutdownRequest(object shutdownObj, RequestContext shutdownContext) + { + // Go through all the existing connections and close them out + foreach (ISqlConnection conn in ActiveConnections.Values) + { + conn.Close(); + } + + await Task.FromResult(0); + } + #endregion #region Private Helpers diff --git a/src/ServiceHost/ConnectionServices/Contracts/ConnectionMessages.cs b/src/ServiceHost/ConnectionServices/Contracts/ConnectionMessages.cs index ddbca266..20463704 100644 --- a/src/ServiceHost/ConnectionServices/Contracts/ConnectionMessages.cs +++ b/src/ServiceHost/ConnectionServices/Contracts/ConnectionMessages.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices.Contracts @@ -42,7 +43,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices.Contracts /// /// Gets or sets the connection id /// - public int ConnectionId { get; set; } + public Guid ConnectionId { get; set; } /// /// Gets or sets any connection error messages diff --git a/src/ServiceHost/ConnectionServices/Contracts/ISqlConnection.cs b/src/ServiceHost/ConnectionServices/Contracts/ISqlConnection.cs index 3ee1cb73..026c124f 100644 --- a/src/ServiceHost/ConnectionServices/Contracts/ISqlConnection.cs +++ b/src/ServiceHost/ConnectionServices/Contracts/ISqlConnection.cs @@ -3,6 +3,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System; using System.Data; using System.Threading; using System.Threading.Tasks; @@ -14,14 +15,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices.Contracts /// public interface ISqlConnection : IDbConnection { - ///// - ///// Open a connection to the provided connection string - ///// - ///// - //void OpenDatabaseConnection(string connectionString); - - //IEnumerable GetServerObjects(); - string DataSource { get; } string ServerVersion { get; } diff --git a/src/ServiceHost/ConnectionServices/Contracts/SqlConnection.cs b/src/ServiceHost/ConnectionServices/Contracts/SqlConnection.cs index ee08af1a..8e39f7d4 100644 --- a/src/ServiceHost/ConnectionServices/Contracts/SqlConnection.cs +++ b/src/ServiceHost/ConnectionServices/Contracts/SqlConnection.cs @@ -32,29 +32,6 @@ namespace Microsoft.SqlTools.ServiceLayer.ConnectionServices.Contracts connection = new SqlConnection(connectionString); } - ///// - ///// Gets a list of database server schema objects - ///// - ///// - //public IEnumerable GetServerObjects() - //{ - // // Select the values from sys.tables to give a super basic - // // autocomplete experience. This will be replaced by SMO. - // SqlCommand command = connection.CreateCommand(); - // command.CommandText = "SELECT name FROM sys.tables"; - // command.CommandTimeout = 15; - // command.CommandType = CommandType.Text; - // var reader = command.ExecuteReader(); - - // List results = new List(); - // while (reader.Read()) - // { - // results.Add(reader[0].ToString()); - // } - - // return results; - //} - #region ISqlConnection Implementation #region Properties diff --git a/src/ServiceHost/LanguageServices/AutoCompleteService.cs b/src/ServiceHost/LanguageServices/AutoCompleteService.cs index 67981ae5..5001e1cc 100644 --- a/src/ServiceHost/LanguageServices/AutoCompleteService.cs +++ b/src/ServiceHost/LanguageServices/AutoCompleteService.cs @@ -5,8 +5,11 @@ using System; using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; using System.Threading.Tasks; -using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.ConnectionServices; +using Microsoft.SqlTools.ServiceLayer.ConnectionServices.Contracts; using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; @@ -60,11 +63,24 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices /// /// Update the cached autocomplete candidate list when the user connects to a database + /// TODO: Update with refactoring/async /// /// public async Task UpdateAutoCompleteCache(ISqlConnection connection) { - AutoCompleteList = connection.GetServerObjects(); + IDbCommand command = connection.CreateCommand(); + command.CommandText = "SELECT name FROM sys.tables"; + command.CommandTimeout = 15; + command.CommandType = CommandType.Text; + var reader = command.ExecuteReader(); + + List results = new List(); + while (reader.Read()) + { + results.Add(reader[0].ToString()); + } + + AutoCompleteList = results; await Task.FromResult(0); } diff --git a/src/ServiceHost/LanguageServices/LanguageService.cs b/src/ServiceHost/LanguageServices/LanguageService.cs index eb643c0c..e2fb0cb0 100644 --- a/src/ServiceHost/LanguageServices/LanguageService.cs +++ b/src/ServiceHost/LanguageServices/LanguageService.cs @@ -17,7 +17,8 @@ using Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts; using System.Linq; using Microsoft.SqlServer.Management.SqlParser.Parser; using Location = Microsoft.SqlTools.ServiceLayer.WorkspaceServices.Contracts.Location; -using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.ConnectionServices; +using Microsoft.SqlTools.ServiceLayer.ConnectionServices.Contracts; namespace Microsoft.SqlTools.ServiceLayer.LanguageServices {