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