diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs index d63a5709..edac0010 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs @@ -1044,7 +1044,29 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection { try { - connection.Close(); + bool disconnect = false; + if (connection.ConnectionString != null){ + int totalCount = 0; + foreach (KeyValuePair entry in OwnerToConnectionMap) + { + foreach (DbConnection value in entry.Value.AllConnections) { + if(value.ConnectionString == connection.ConnectionString) { + totalCount++; + } + } + } + + if(totalCount == 1) { + disconnect = true; + } + } + else { + disconnect = true; + } + + if(disconnect) { + connection.Close(); + } } catch (Exception) { 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..aa23fe4f 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; @@ -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); } diff --git a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs index 48a29dec..4d2f8330 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/TableDesigner/TableDesignerService.cs @@ -1833,9 +1833,14 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner private void UpdateTableTitleInfo(TableInfo tableInfo) { var td = GetTableDesigner(tableInfo); + var advancedOpsIndex = tableInfo.Tooltip.LastIndexOf('['); + var advancedOps = ""; + if(advancedOpsIndex > -1){ + 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 a3b0a92a..0e7e1fa7 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs @@ -57,7 +57,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);