mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-02 17:24:50 -05:00
Update connection logic to handle multiple connections per URI (#176)
* Add CancelTokenKey for uniquely identifying cancelations of Connections associated with an OwnerUri and ConnectionType string. * Update ConnectionInfo to use ConcurrentDictionary of DbConnection instances. Add wrapper functions for the ConcurrentDictionary. * Refactor Connect and Disconnect in ConnectionService. * Update ConnectionService: Handle multiple connections per ConnectionInfo. Handle cancelation tokens uniquely identified with CancelTokenKey. Add GetOrOpenConnection() for other services to request an existing or create a new DbConnection. * Add ConnectionType.cs for ConnectionType strings. * Add ConnectionType string to ConnectParams, ConnectionCompleteNotification, DisconnectParams. * Update Query ExecuteInternal to use the dedicated query connection and GetOrOpenConnection(). * Update test library to account for multiple connections in ConnectionInfo. * Write tests ensuring multiple connections don’t create redundant data. * Write tests ensuring database changes affect all connections of a given ConnectionInfo. * Write tests for TRANSACTION statements and temp tables.
This commit is contained in:
@@ -4,8 +4,12 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Connection
|
||||
{
|
||||
@@ -23,7 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
|
||||
OwnerUri = ownerUri;
|
||||
ConnectionDetails = details;
|
||||
ConnectionId = Guid.NewGuid();
|
||||
IntellisenseMetrics = new InteractionMetrics<double>(new int[] { 50, 100, 200, 500, 1000, 2000 });
|
||||
IntellisenseMetrics = new InteractionMetrics<double>(new int[] {50, 100, 200, 500, 1000, 2000});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -39,17 +43,20 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
|
||||
/// <summary>
|
||||
/// Factory used for creating the SQL connection associated with the connection info.
|
||||
/// </summary>
|
||||
public ISqlConnectionFactory Factory {get; private set;}
|
||||
public ISqlConnectionFactory Factory { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Properties used for creating/opening the SQL connection.
|
||||
/// </summary>
|
||||
public ConnectionDetails ConnectionDetails { get; private set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The connection to the SQL database that commands will be run against.
|
||||
/// A map containing all connections to the database that are associated with
|
||||
/// this ConnectionInfo's OwnerUri.
|
||||
/// This is internal for testing access only
|
||||
/// </summary>
|
||||
public DbConnection SqlConnection { get; set; }
|
||||
internal readonly ConcurrentDictionary<string, DbConnection> ConnectionTypeToConnectionMap =
|
||||
new ConcurrentDictionary<string, DbConnection>();
|
||||
|
||||
/// <summary>
|
||||
/// Intellisense Metrics
|
||||
@@ -60,8 +67,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
|
||||
/// Returns true is the db connection is to a SQL db
|
||||
/// </summary>
|
||||
public bool IsAzure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
/// Returns true if the sql connection is to a DW instance
|
||||
/// </summary>
|
||||
public bool IsSqlDW { get; set; }
|
||||
@@ -71,5 +77,86 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
|
||||
/// </summary>
|
||||
public int MajorVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// All DbConnection instances held by this ConnectionInfo
|
||||
/// </summary>
|
||||
public ICollection<DbConnection> AllConnections
|
||||
{
|
||||
get
|
||||
{
|
||||
return ConnectionTypeToConnectionMap.Values;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All connection type strings held by this ConnectionInfo
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public ICollection<string> AllConnectionTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return ConnectionTypeToConnectionMap.Keys;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The count of DbConnectioninstances held by this ConnectionInfo
|
||||
/// </summary>
|
||||
public int CountConnections
|
||||
{
|
||||
get
|
||||
{
|
||||
return ConnectionTypeToConnectionMap.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to get the DbConnection associated with the given connection type string.
|
||||
/// </summary>
|
||||
/// <returns>true if a connection with type connectionType was located and out connection was set,
|
||||
/// false otherwise </returns>
|
||||
/// <exception cref="ArgumentException">Thrown when connectionType is null or empty</exception>
|
||||
public bool TryGetConnection(string connectionType, out DbConnection connection)
|
||||
{
|
||||
Validate.IsNotNullOrEmptyString("Connection Type", connectionType);
|
||||
return ConnectionTypeToConnectionMap.TryGetValue(connectionType, out connection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a DbConnection to this object and associates it with the given
|
||||
/// connection type string. If a connection already exists with an identical
|
||||
/// connection type string, it is not overwritten. Ignores calls where connectionType = null
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">Thrown when connectionType is null or empty</exception>
|
||||
public void AddConnection(string connectionType, DbConnection connection)
|
||||
{
|
||||
Validate.IsNotNullOrEmptyString("Connection Type", connectionType);
|
||||
ConnectionTypeToConnectionMap.TryAdd(connectionType, connection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the single DbConnection instance associated with string connectionType
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentException">Thrown when connectionType is null or empty</exception>
|
||||
public void RemoveConnection(string connectionType)
|
||||
{
|
||||
Validate.IsNotNullOrEmptyString("Connection Type", connectionType);
|
||||
DbConnection connection;
|
||||
ConnectionTypeToConnectionMap.TryRemove(connectionType, out connection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all DbConnection instances held by this object
|
||||
/// </summary>
|
||||
public void RemoveAllConnections()
|
||||
{
|
||||
foreach (var type in AllConnectionTypes)
|
||||
{
|
||||
DbConnection connection;
|
||||
ConnectionTypeToConnectionMap.TryRemove(type, out connection);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user