diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs
index 0c6397f6..ccaff015 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs
@@ -586,6 +586,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
}
}
+ ///
+ /// Gets or sets the connection name
+ ///
+ public string ConnectionName
+ {
+ get
+ {
+ return GetOptionValue("connectionName");
+ }
+ set
+ {
+ SetOptionValue("connectionName", value);
+ }
+ }
+
///
/// Gets or sets the database display name
///
diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ConnectedBindingQueue.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ConnectedBindingQueue.cs
index 2e7b30f3..3b8905e3 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ConnectedBindingQueue.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ConnectedBindingQueue.cs
@@ -6,6 +6,7 @@
#nullable disable
using System;
+using System.Collections.Generic;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.SmoMetadataProvider;
using Microsoft.SqlServer.Management.SqlParser.Binder;
@@ -70,7 +71,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
public ConnectedBindingQueue()
: this(true)
- {
+ {
}
public ConnectedBindingQueue(bool needsMetadata)
@@ -90,7 +91,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
///
///
internal static string GetConnectionContextKey(ConnectionDetails details)
- {
+ {
string key = string.Format("{0}_{1}_{2}_{3}",
details.ServerName ?? "NULL",
details.DatabaseName ?? "NULL",
@@ -108,6 +109,39 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
key += "_" + details.GroupId;
}
+ if (!string.IsNullOrEmpty(details.ConnectionName))
+ {
+ key += "_" + details.ConnectionName;
+ }
+
+ // Additional properties that are used to distinguish the connection (besides password)
+ // These are so that multiple connections can connect to the same target, with different settings.
+ foreach (KeyValuePair entry in details.Options)
+ {
+ // Filter out properties we already have or don't want (password)
+ if (entry.Key != "server" && entry.Key != "database" && entry.Key != "user"
+ && entry.Key != "authenticationType" && entry.Key != "databaseDisplayName"
+ && entry.Key != "groupId" && entry.Key != "password" && entry.Key != "connectionName")
+ {
+ // Boolean values are explicitly labeled true or false instead of undefined.
+ if (entry.Value is bool)
+ {
+ if ((bool)entry.Value)
+ {
+ key += "_" + entry.Key + ":true";
+ }
+ else
+ {
+ key += "_" + entry.Key + ":false";
+ }
+ }
+ else if (!string.IsNullOrEmpty(entry.Value as String))
+ {
+ key += "_" + entry.Key + ":" + entry.Value;
+ }
+ }
+ }
+
return Uri.EscapeUriString(key);
}
@@ -120,7 +154,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
return string.Format("{0}_{1}",
serverName ?? "NULL",
databaseName ?? "NULL");
-
+
}
public void CloseConnections(string serverName, string databaseName, int millisecondsTimeout)
@@ -198,7 +232,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
try
{
bindingContext.BindingLock.Reset();
-
+
// populate the binding context to work with the SMO metadata provider
bindingContext.ServerConnection = connectionOpener.OpenServerConnection(connInfo, featureName);
@@ -210,19 +244,19 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
this.CurrentSettings.SqlTools.IntelliSense.LowerCaseSuggestions.Value
? CasingStyle.Lowercase : CasingStyle.Uppercase;
bindingContext.Binder = BinderProvider.CreateBinder(bindingContext.SmoMetadataProvider);
- }
-
+ }
+
bindingContext.BindingTimeout = ConnectedBindingQueue.DefaultBindingTimeout;
bindingContext.IsConnected = true;
}
catch (Exception)
{
bindingContext.IsConnected = false;
- }
+ }
finally
{
bindingContext.BindingLock.Set();
- }
+ }
}
return connectionKey;
diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs
index 84b5b133..de31b69b 100644
--- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs
+++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs
@@ -1830,9 +1830,11 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
private void UpdateTableTitleInfo(TableInfo tableInfo)
{
var td = GetTableDesigner(tableInfo);
+ var advancedOpsIndex = tableInfo.Tooltip.LastIndexOf('[');
+ var advancedOps = tableInfo.Tooltip.Substring(advancedOpsIndex);
tableInfo.Title = td.TableViewModel.FullName;
var tableParent = tableInfo.Server == null ? tableInfo.ProjectFilePath : string.Format("{0} - {1}", tableInfo.Server, tableInfo.Database);
- tableInfo.Tooltip = string.Format("{0} - {1}", tableParent, tableInfo.Title);
+ tableInfo.Tooltip = string.Format("{0} - {1} {2}", tableParent, tableInfo.Title, advancedOps);
}
private Dictionary GetMetadata(TableInfo tableInfo)
diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs
index 2ebd0198..d340b16a 100644
--- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs
+++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs
@@ -56,7 +56,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
ConnectedBindingContext connectedBindingContext = new ConnectedBindingContext();
connectedBindingContext.ServerConnection = new ServerConnection(new SqlConnection(fakeConnectionString));
connectedBindingQueue = new ConnectedBindingQueue(false);
- connectedBindingQueue.BindingContextMap.Add($"{details.ServerName}_{details.DatabaseName}_{details.UserName}_NULL", connectedBindingContext);
+ connectedBindingQueue.BindingContextMap.Add($"{details.ServerName}_{details.DatabaseName}_{details.UserName}_NULL_persistSecurityInfo:true", connectedBindingContext);
connectedBindingQueue.BindingContextTasks.Add(connectedBindingContext, Task.Run(() => null));
mockConnectionOpener = new Mock();
connectedBindingQueue.SetConnectionOpener(mockConnectionOpener.Object);