diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs index 796871bd..42e3c3c3 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs @@ -1,232 +1,232 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Data; -using System.Data.Common; -using System.Data.SqlClient; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.SqlTools.Hosting.Protocol; -using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; -using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; -using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; -using Microsoft.SqlTools.ServiceLayer.SqlContext; -using Microsoft.SqlTools.ServiceLayer.Workspace; -using Microsoft.SqlServer.Management.Common; -using Microsoft.SqlTools.Utility; - -namespace Microsoft.SqlTools.ServiceLayer.Connection -{ - /// - /// Main class for the Connection Management services - /// - public class ConnectionService - { - /// - /// Singleton service instance - /// - private static readonly Lazy instance - = new Lazy(() => new ConnectionService()); - - /// - /// Gets the singleton service instance - /// - public static ConnectionService Instance - { - get - { - return instance.Value; - } - } - - /// - /// The SQL connection factory object - /// - private ISqlConnectionFactory connectionFactory; - - private readonly Dictionary ownerToConnectionMap = new Dictionary(); - - /// - /// A map containing all CancellationTokenSource objects that are associated with a given URI/ConnectionType pair. - /// Entries in this map correspond to DbConnection instances that are in the process of connecting. - /// - private readonly ConcurrentDictionary cancelTupleToCancellationTokenSourceMap = - new ConcurrentDictionary(); - - private readonly object cancellationTokenSourceLock = new object(); - - /// - /// Map from script URIs to ConnectionInfo objects - /// This is internal for testing access only - /// - internal Dictionary OwnerToConnectionMap - { - get - { - return this.ownerToConnectionMap; - } - } - - /// - /// Service host object for sending/receiving requests/events. - /// Internal for testing purposes. - /// - internal IProtocolEndpoint ServiceHost - { - get; - set; - } - - /// - /// Default constructor should be private since it's a singleton class, but we need a constructor - /// for use in unit test mocking. - /// - public ConnectionService() - { - } - - /// - /// Callback for onconnection handler - /// - /// - public delegate Task OnConnectionHandler(ConnectionInfo info); - - /// - /// Callback for ondisconnect handler - /// - public delegate Task OnDisconnectHandler(ConnectionSummary summary, string ownerUri); - - /// - /// List of onconnection handlers - /// - private readonly List onConnectionActivities = new List(); - - /// - /// List of ondisconnect handlers - /// - private readonly List onDisconnectActivities = new List(); - - /// - /// Gets the SQL connection factory instance - /// - public ISqlConnectionFactory ConnectionFactory - { - get - { - if (this.connectionFactory == null) - { - this.connectionFactory = new SqlConnectionFactory(); - } - return this.connectionFactory; - } - - internal set { this.connectionFactory = value; } - } - - /// - /// Test constructor that injects dependency interfaces - /// - /// - public ConnectionService(ISqlConnectionFactory testFactory) - { - this.connectionFactory = testFactory; - } - - // Attempts to link a URI to an actively used connection for this URI - public virtual bool TryFindConnection(string ownerUri, out ConnectionInfo connectionInfo) - { - return this.ownerToConnectionMap.TryGetValue(ownerUri, out connectionInfo); - } - - /// - /// Validates the given ConnectParams object. - /// - /// The params to validate - /// A ConnectionCompleteParams object upon validation error, - /// null upon validation success - public ConnectionCompleteParams ValidateConnectParams(ConnectParams connectionParams) - { - string paramValidationErrorMessage; - if (connectionParams == null) - { - return new ConnectionCompleteParams - { - Messages = SR.ConnectionServiceConnectErrorNullParams - }; - } - if (!connectionParams.IsValid(out paramValidationErrorMessage)) - { - return new ConnectionCompleteParams - { - OwnerUri = connectionParams.OwnerUri, - Messages = paramValidationErrorMessage - }; - } - - // return null upon success - return null; - } - - /// - /// Open a connection with the specified ConnectParams - /// - public virtual async Task Connect(ConnectParams connectionParams) - { - // Validate parameters - ConnectionCompleteParams validationResults = ValidateConnectParams(connectionParams); - if (validationResults != null) - { - return validationResults; - } - - // If there is no ConnectionInfo in the map, create a new ConnectionInfo, - // but wait until later when we are connected to add it to the map. - ConnectionInfo connectionInfo; - bool connectionChanged = false; - if (!ownerToConnectionMap.TryGetValue(connectionParams.OwnerUri, out connectionInfo)) - { - connectionInfo = new ConnectionInfo(ConnectionFactory, connectionParams.OwnerUri, connectionParams.Connection); - } +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Data.SqlClient; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; +using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; +using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.ServiceLayer.Workspace; +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlTools.Utility; + +namespace Microsoft.SqlTools.ServiceLayer.Connection +{ + /// + /// Main class for the Connection Management services + /// + public class ConnectionService + { + /// + /// Singleton service instance + /// + private static readonly Lazy instance + = new Lazy(() => new ConnectionService()); + + /// + /// Gets the singleton service instance + /// + public static ConnectionService Instance + { + get + { + return instance.Value; + } + } + + /// + /// The SQL connection factory object + /// + private ISqlConnectionFactory connectionFactory; + + private readonly Dictionary ownerToConnectionMap = new Dictionary(); + + /// + /// A map containing all CancellationTokenSource objects that are associated with a given URI/ConnectionType pair. + /// Entries in this map correspond to DbConnection instances that are in the process of connecting. + /// + private readonly ConcurrentDictionary cancelTupleToCancellationTokenSourceMap = + new ConcurrentDictionary(); + + private readonly object cancellationTokenSourceLock = new object(); + + /// + /// Map from script URIs to ConnectionInfo objects + /// This is internal for testing access only + /// + internal Dictionary OwnerToConnectionMap + { + get + { + return this.ownerToConnectionMap; + } + } + + /// + /// Service host object for sending/receiving requests/events. + /// Internal for testing purposes. + /// + internal IProtocolEndpoint ServiceHost + { + get; + set; + } + + /// + /// Default constructor should be private since it's a singleton class, but we need a constructor + /// for use in unit test mocking. + /// + public ConnectionService() + { + } + + /// + /// Callback for onconnection handler + /// + /// + public delegate Task OnConnectionHandler(ConnectionInfo info); + + /// + /// Callback for ondisconnect handler + /// + public delegate Task OnDisconnectHandler(ConnectionSummary summary, string ownerUri); + + /// + /// List of onconnection handlers + /// + private readonly List onConnectionActivities = new List(); + + /// + /// List of ondisconnect handlers + /// + private readonly List onDisconnectActivities = new List(); + + /// + /// Gets the SQL connection factory instance + /// + public ISqlConnectionFactory ConnectionFactory + { + get + { + if (this.connectionFactory == null) + { + this.connectionFactory = new SqlConnectionFactory(); + } + return this.connectionFactory; + } + + internal set { this.connectionFactory = value; } + } + + /// + /// Test constructor that injects dependency interfaces + /// + /// + public ConnectionService(ISqlConnectionFactory testFactory) + { + this.connectionFactory = testFactory; + } + + // Attempts to link a URI to an actively used connection for this URI + public virtual bool TryFindConnection(string ownerUri, out ConnectionInfo connectionInfo) + { + return this.ownerToConnectionMap.TryGetValue(ownerUri, out connectionInfo); + } + + /// + /// Validates the given ConnectParams object. + /// + /// The params to validate + /// A ConnectionCompleteParams object upon validation error, + /// null upon validation success + public ConnectionCompleteParams ValidateConnectParams(ConnectParams connectionParams) + { + string paramValidationErrorMessage; + if (connectionParams == null) + { + return new ConnectionCompleteParams + { + Messages = SR.ConnectionServiceConnectErrorNullParams + }; + } + if (!connectionParams.IsValid(out paramValidationErrorMessage)) + { + return new ConnectionCompleteParams + { + OwnerUri = connectionParams.OwnerUri, + Messages = paramValidationErrorMessage + }; + } + + // return null upon success + return null; + } + + /// + /// Open a connection with the specified ConnectParams + /// + public virtual async Task Connect(ConnectParams connectionParams) + { + // Validate parameters + ConnectionCompleteParams validationResults = ValidateConnectParams(connectionParams); + if (validationResults != null) + { + return validationResults; + } + + // If there is no ConnectionInfo in the map, create a new ConnectionInfo, + // but wait until later when we are connected to add it to the map. + ConnectionInfo connectionInfo; + bool connectionChanged = false; + if (!ownerToConnectionMap.TryGetValue(connectionParams.OwnerUri, out connectionInfo)) + { + connectionInfo = new ConnectionInfo(ConnectionFactory, connectionParams.OwnerUri, connectionParams.Connection); + } else if (IsConnectionChanged(connectionParams, connectionInfo)) { // We are actively changing the connection information for this connection. We must disconnect // all active connections, since it represents a full context change connectionChanged = true; - } - + } + DisconnectExistingConnectionIfNeeded(connectionParams, connectionInfo, disconnectAll: connectionChanged); - + if (connectionChanged) { connectionInfo = new ConnectionInfo(ConnectionFactory, connectionParams.OwnerUri, connectionParams.Connection); } // Try to open a connection with the given ConnectParams - ConnectionCompleteParams response = await TryOpenConnection(connectionInfo, connectionParams); - if (response != null) - { - return response; + ConnectionCompleteParams response = await TryOpenConnection(connectionInfo, connectionParams); + if (response != null) + { + return response; } // If this is the first connection for this URI, add the ConnectionInfo to the map bool addToMap = connectionChanged || !ownerToConnectionMap.ContainsKey(connectionParams.OwnerUri); - if (addToMap) - { - ownerToConnectionMap[connectionParams.OwnerUri] = connectionInfo; - } - - // Return information about the connected SQL Server instance - ConnectionCompleteParams completeParams = GetConnectionCompleteParams(connectionParams.Type, connectionInfo); - // Invoke callback notifications - InvokeOnConnectionActivities(connectionInfo, connectionParams); - - return completeParams; + if (addToMap) + { + ownerToConnectionMap[connectionParams.OwnerUri] = connectionInfo; + } + + // Return information about the connected SQL Server instance + ConnectionCompleteParams completeParams = GetConnectionCompleteParams(connectionParams.Type, connectionInfo); + // Invoke callback notifications + InvokeOnConnectionActivities(connectionInfo, connectionParams); + + return completeParams; } private bool IsConnectionChanged(ConnectParams connectionParams, ConnectionInfo connectionInfo) @@ -248,806 +248,806 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection { // Resolve if it is an existing connection // Disconnect active connection if the URI is already connected for this connection type - DbConnection existingConnection; - if (connectionInfo.TryGetConnection(connectionParams.Type, out existingConnection)) - { - var disconnectParams = new DisconnectParams() - { + DbConnection existingConnection; + if (connectionInfo.TryGetConnection(connectionParams.Type, out existingConnection)) + { + var disconnectParams = new DisconnectParams() + { OwnerUri = connectionParams.OwnerUri, - Type = disconnectAll ? null : connectionParams.Type - }; - Disconnect(disconnectParams); + Type = disconnectAll ? null : connectionParams.Type + }; + Disconnect(disconnectParams); } } - /// - /// Creates a ConnectionCompleteParams as a response to a successful connection. - /// Also sets the DatabaseName and IsAzure properties of ConnectionInfo. - /// - /// A ConnectionCompleteParams in response to the successful connection - private ConnectionCompleteParams GetConnectionCompleteParams(string connectionType, ConnectionInfo connectionInfo) - { - ConnectionCompleteParams response = new ConnectionCompleteParams { OwnerUri = connectionInfo.OwnerUri, Type = connectionType }; - - try - { - DbConnection connection; - connectionInfo.TryGetConnection(connectionType, out connection); - - // Update with the actual database name in connectionInfo and result - // Doing this here as we know the connection is open - expect to do this only on connecting - connectionInfo.ConnectionDetails.DatabaseName = connection.Database; - response.ConnectionSummary = new ConnectionSummary - { - ServerName = connectionInfo.ConnectionDetails.ServerName, - DatabaseName = connectionInfo.ConnectionDetails.DatabaseName, - UserName = connectionInfo.ConnectionDetails.UserName, - }; - - response.ConnectionId = connectionInfo.ConnectionId.ToString(); - - var reliableConnection = connection as ReliableSqlConnection; - DbConnection underlyingConnection = reliableConnection != null - ? reliableConnection.GetUnderlyingConnection() - : connection; - - ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(underlyingConnection); - response.ServerInfo = new ServerInfo - { - ServerMajorVersion = serverInfo.ServerMajorVersion, - ServerMinorVersion = serverInfo.ServerMinorVersion, - ServerReleaseVersion = serverInfo.ServerReleaseVersion, - EngineEditionId = serverInfo.EngineEditionId, - ServerVersion = serverInfo.ServerVersion, - ServerLevel = serverInfo.ServerLevel, - ServerEdition = serverInfo.ServerEdition, - IsCloud = serverInfo.IsCloud, - AzureVersion = serverInfo.AzureVersion, - OsVersion = serverInfo.OsVersion - }; - connectionInfo.IsAzure = serverInfo.IsCloud; - connectionInfo.MajorVersion = serverInfo.ServerMajorVersion; - connectionInfo.IsSqlDW = (serverInfo.EngineEditionId == (int)DatabaseEngineEdition.SqlDataWarehouse); - } - catch (Exception ex) - { - response.Messages = ex.ToString(); - } - - return response; - } - - /// - /// Tries to create and open a connection with the given ConnectParams. - /// - /// null upon success, a ConnectionCompleteParams detailing the error upon failure - private async Task TryOpenConnection(ConnectionInfo connectionInfo, ConnectParams connectionParams) - { - CancellationTokenSource source = null; - DbConnection connection = null; - CancelTokenKey cancelKey = new CancelTokenKey { OwnerUri = connectionParams.OwnerUri, Type = connectionParams.Type }; - ConnectionCompleteParams response = new ConnectionCompleteParams { OwnerUri = connectionInfo.OwnerUri, Type = connectionParams.Type }; - - try - { - // build the connection string from the input parameters - string connectionString = BuildConnectionString(connectionInfo.ConnectionDetails); - - // create a sql connection instance - connection = connectionInfo.Factory.CreateSqlConnection(connectionString); - connectionInfo.AddConnection(connectionParams.Type, connection); - - // Add a cancellation token source so that the connection OpenAsync() can be cancelled - source = new CancellationTokenSource(); - // Locking here to perform two operations as one atomic operation - lock (cancellationTokenSourceLock) - { - // If the URI is currently connecting from a different request, cancel it before we try to connect - CancellationTokenSource currentSource; - if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out currentSource)) - { - currentSource.Cancel(); - } - cancelTupleToCancellationTokenSourceMap[cancelKey] = source; - } - - // Open the connection - await connection.OpenAsync(source.Token); - } - catch (SqlException ex) - { - response.ErrorNumber = ex.Number; - response.ErrorMessage = ex.Message; - response.Messages = ex.ToString(); - return response; - } - catch (OperationCanceledException) - { - // OpenAsync was cancelled - response.Messages = SR.ConnectionServiceConnectionCanceled; - return response; - } - catch (Exception ex) - { - response.ErrorMessage = ex.Message; - response.Messages = ex.ToString(); - return response; - } - finally - { - // Remove our cancellation token from the map since we're no longer connecting - // Using a lock here to perform two operations as one atomic operation - lock (cancellationTokenSourceLock) - { - // Only remove the token from the map if it is the same one created by this request - CancellationTokenSource sourceValue; - if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out sourceValue) && sourceValue == source) - { - cancelTupleToCancellationTokenSourceMap.TryRemove(cancelKey, out sourceValue); - } - source?.Dispose(); - } - } - - // Return null upon success - return null; - } - - /// - /// Gets the existing connection with the given URI and connection type string. If none exists, - /// creates a new connection. This cannot be used to create a default connection or to create a - /// connection if a default connection does not exist. - /// - /// A DB connection for the connection type requested - public async Task GetOrOpenConnection(string ownerUri, string connectionType) - { - Validate.IsNotNullOrEmptyString(nameof(ownerUri), ownerUri); - Validate.IsNotNullOrEmptyString(nameof(connectionType), connectionType); - - // Try to get the ConnectionInfo, if it exists - ConnectionInfo connectionInfo; - if (!ownerToConnectionMap.TryGetValue(ownerUri, out connectionInfo)) - { - throw new ArgumentOutOfRangeException(SR.ConnectionServiceListDbErrorNotConnected(ownerUri)); - } - - // Make sure a default connection exists - DbConnection defaultConnection; - if (!connectionInfo.TryGetConnection(ConnectionType.Default, out defaultConnection)) - { - throw new InvalidOperationException(SR.ConnectionServiceDbErrorDefaultNotConnected(ownerUri)); - } - - // Try to get the DbConnection - DbConnection connection; - if (!connectionInfo.TryGetConnection(connectionType, out connection) && ConnectionType.Default != connectionType) - { - // If the DbConnection does not exist and is not the default connection, create one. - // We can't create the default (initial) connection here because we won't have a ConnectionDetails - // if Connect() has not yet been called. - ConnectParams connectParams = new ConnectParams - { - OwnerUri = ownerUri, - Connection = connectionInfo.ConnectionDetails, - Type = connectionType - }; - await Connect(connectParams); - connectionInfo.TryGetConnection(connectionType, out connection); - } - - return connection; - } - - /// - /// Cancel a connection that is in the process of opening. - /// - public bool CancelConnect(CancelConnectParams cancelParams) - { - // Validate parameters - if (cancelParams == null || string.IsNullOrEmpty(cancelParams.OwnerUri)) - { - return false; - } - - CancelTokenKey cancelKey = new CancelTokenKey - { - OwnerUri = cancelParams.OwnerUri, - Type = cancelParams.Type - }; - - // Cancel any current connection attempts for this URI - CancellationTokenSource source; - if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out source)) - { - try - { - source.Cancel(); - return true; - } - catch - { - return false; - } - } - - return false; - } - - /// - /// Close a connection with the specified connection details. - /// - public bool Disconnect(DisconnectParams disconnectParams) - { - // Validate parameters - if (disconnectParams == null || string.IsNullOrEmpty(disconnectParams.OwnerUri)) - { - return false; - } - - // Cancel if we are in the middle of connecting - if (CancelConnections(disconnectParams.OwnerUri, disconnectParams.Type)) - { - return false; - } - - // Lookup the ConnectionInfo owned by the URI - ConnectionInfo info; - if (!ownerToConnectionMap.TryGetValue(disconnectParams.OwnerUri, out info)) - { - return false; - } - - // Call Close() on the connections we want to disconnect - // If no connections were located, return false - if (!CloseConnections(info, disconnectParams.Type)) - { - return false; - } - - // Remove the disconnected connections from the ConnectionInfo map - if (disconnectParams.Type == null) - { - info.RemoveAllConnections(); - } - else - { - info.RemoveConnection(disconnectParams.Type); - } - - // If the ConnectionInfo has no more connections, remove the ConnectionInfo - if (info.CountConnections == 0) - { - ownerToConnectionMap.Remove(disconnectParams.OwnerUri); - } - - // Handle Telemetry disconnect events if we are disconnecting the default connection - if (disconnectParams.Type == null || disconnectParams.Type == ConnectionType.Default) - { - HandleDisconnectTelemetry(info); - InvokeOnDisconnectionActivities(info); - } - - // Return true upon success - return true; - } - - /// - /// Cancel connections associated with the given ownerUri. - /// If connectionType is not null, cancel the connection with the given connectionType - /// If connectionType is null, cancel all pending connections associated with ownerUri. - /// - /// true if a single pending connection associated with the non-null connectionType was - /// found and cancelled, false otherwise - private bool CancelConnections(string ownerUri, string connectionType) - { - // Cancel the connection of the given type - if (connectionType != null) - { - // If we are trying to disconnect a specific connection and it was just cancelled, - // this will return true - return CancelConnect(new CancelConnectParams() { OwnerUri = ownerUri, Type = connectionType }); - } - - // Cancel all pending connections - foreach (var entry in cancelTupleToCancellationTokenSourceMap) - { - string entryConnectionUri = entry.Key.OwnerUri; - string entryConnectionType = entry.Key.Type; - if (ownerUri.Equals(entryConnectionUri)) - { - CancelConnect(new CancelConnectParams() { OwnerUri = ownerUri, Type = entryConnectionType }); - } - } - - return false; - } - - /// - /// Closes DbConnections associated with the given ConnectionInfo. - /// If connectionType is not null, closes the DbConnection with the type given by connectionType. - /// If connectionType is null, closes all DbConnections. - /// - /// true if connections were found and attempted to be closed, - /// false if no connections were found - private bool CloseConnections(ConnectionInfo connectionInfo, string connectionType) - { - ICollection connectionsToDisconnect = new List(); - if (connectionType == null) - { - connectionsToDisconnect = connectionInfo.AllConnections; - } - else - { - // Make sure there is an existing connection of this type - DbConnection connection; - if (!connectionInfo.TryGetConnection(connectionType, out connection)) - { - return false; - } - connectionsToDisconnect.Add(connection); - } - - if (connectionsToDisconnect.Count == 0) - { - return false; - } - - foreach (DbConnection connection in connectionsToDisconnect) - { - try - { - connection.Close(); - } - catch (Exception) - { - // Ignore - } - } - - return true; - } - - /// - /// List all databases on the server specified - /// - public ListDatabasesResponse ListDatabases(ListDatabasesParams listDatabasesParams) - { - // Verify parameters - var owner = listDatabasesParams.OwnerUri; - if (string.IsNullOrEmpty(owner)) - { - throw new ArgumentException(SR.ConnectionServiceListDbErrorNullOwnerUri); - } - - // Use the existing connection as a base for the search - ConnectionInfo info; - if (!TryFindConnection(owner, out info)) - { - throw new Exception(SR.ConnectionServiceListDbErrorNotConnected(owner)); - } - ConnectionDetails connectionDetails = info.ConnectionDetails.Clone(); - - // Connect to master and query sys.databases - connectionDetails.DatabaseName = "master"; - var connection = this.ConnectionFactory.CreateSqlConnection(BuildConnectionString(connectionDetails)); - connection.Open(); - - List results = new List(); - var systemDatabases = new[] {"master", "model", "msdb", "tempdb"}; - using (DbCommand command = connection.CreateCommand()) - { - command.CommandText = "SELECT name FROM sys.databases ORDER BY name ASC"; - command.CommandTimeout = 15; - command.CommandType = CommandType.Text; - - using (var reader = command.ExecuteReader()) - { - while (reader.Read()) - { - results.Add(reader[0].ToString()); - } - } - } - - // Put system databases at the top of the list - results = - results.Where(s => systemDatabases.Any(s.Equals)).Concat( - results.Where(s => systemDatabases.All(x => !s.Equals(x)))).ToList(); - - connection.Close(); - - ListDatabasesResponse response = new ListDatabasesResponse(); - response.DatabaseNames = results.ToArray(); - - return response; - } - - public void InitializeService(IProtocolEndpoint serviceHost) - { - this.ServiceHost = serviceHost; - - // Register request and event handlers with the Service Host - serviceHost.SetRequestHandler(ConnectionRequest.Type, HandleConnectRequest); - serviceHost.SetRequestHandler(CancelConnectRequest.Type, HandleCancelConnectRequest); - serviceHost.SetRequestHandler(DisconnectRequest.Type, HandleDisconnectRequest); - serviceHost.SetRequestHandler(ListDatabasesRequest.Type, HandleListDatabasesRequest); - - // Register the configuration update handler - WorkspaceService.Instance.RegisterConfigChangeCallback(HandleDidChangeConfigurationNotification); - } - - /// - /// Add a new method to be called when the onconnection request is submitted - /// - /// - public void RegisterOnConnectionTask(OnConnectionHandler activity) - { - onConnectionActivities.Add(activity); - } - - /// - /// Add a new method to be called when the ondisconnect request is submitted - /// - public void RegisterOnDisconnectTask(OnDisconnectHandler activity) - { - onDisconnectActivities.Add(activity); - } - - /// - /// Handle new connection requests - /// - /// - /// - /// - protected async Task HandleConnectRequest( - ConnectParams connectParams, - RequestContext requestContext) - { - Logger.Write(LogLevel.Verbose, "HandleConnectRequest"); - - try - { - RunConnectRequestHandlerTask(connectParams); - await requestContext.SendResult(true); - } - catch - { - await requestContext.SendResult(false); - } - } - - private void RunConnectRequestHandlerTask(ConnectParams connectParams) - { - // create a task to connect asynchronously so that other requests are not blocked in the meantime - Task.Run(async () => - { - try - { - // result is null if the ConnectParams was successfully validated - ConnectionCompleteParams result = ValidateConnectParams(connectParams); - if (result != null) - { - await ServiceHost.SendEvent(ConnectionCompleteNotification.Type, result); - return; - } - - // open connection based on request details - result = await Connect(connectParams); - await ServiceHost.SendEvent(ConnectionCompleteNotification.Type, result); - } - catch (Exception ex) - { - ConnectionCompleteParams result = new ConnectionCompleteParams() - { - Messages = ex.ToString() - }; - await ServiceHost.SendEvent(ConnectionCompleteNotification.Type, result); - } - }); - } - - /// - /// Handle cancel connect requests - /// - protected async Task HandleCancelConnectRequest( - CancelConnectParams cancelParams, - RequestContext requestContext) - { - Logger.Write(LogLevel.Verbose, "HandleCancelConnectRequest"); - - try - { - bool result = CancelConnect(cancelParams); - await requestContext.SendResult(result); - } - catch(Exception ex) - { - await requestContext.SendError(ex.ToString()); - } - } - - /// - /// Handle disconnect requests - /// - protected async Task HandleDisconnectRequest( - DisconnectParams disconnectParams, - RequestContext requestContext) - { - Logger.Write(LogLevel.Verbose, "HandleDisconnectRequest"); - - try - { - bool result = Instance.Disconnect(disconnectParams); - await requestContext.SendResult(result); - } - catch(Exception ex) - { - await requestContext.SendError(ex.ToString()); - } - - } - - /// - /// Handle requests to list databases on the current server - /// - protected async Task HandleListDatabasesRequest( - ListDatabasesParams listDatabasesParams, - RequestContext requestContext) - { - Logger.Write(LogLevel.Verbose, "ListDatabasesRequest"); - - try - { - ListDatabasesResponse result = Instance.ListDatabases(listDatabasesParams); - await requestContext.SendResult(result); - } - catch(Exception ex) - { - await requestContext.SendError(ex.ToString()); - } - } - - public Task HandleDidChangeConfigurationNotification( - SqlToolsSettings newSettings, - SqlToolsSettings oldSettings, - EventContext eventContext) - { - return Task.FromResult(true); - } - - /// - /// Build a connection string from a connection details instance - /// - /// - public static string BuildConnectionString(ConnectionDetails connectionDetails) - { - SqlConnectionStringBuilder connectionBuilder = new SqlConnectionStringBuilder - { - ["Data Source"] = connectionDetails.ServerName, - ["User Id"] = connectionDetails.UserName, - ["Password"] = connectionDetails.Password - }; - - // Check for any optional parameters - if (!string.IsNullOrEmpty(connectionDetails.DatabaseName)) - { - connectionBuilder["Initial Catalog"] = connectionDetails.DatabaseName; - } - if (!string.IsNullOrEmpty(connectionDetails.AuthenticationType)) - { - switch(connectionDetails.AuthenticationType) - { - case "Integrated": - connectionBuilder.IntegratedSecurity = true; - break; - case "SqlLogin": - break; - default: - throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAuthType(connectionDetails.AuthenticationType)); - } - } - if (connectionDetails.Encrypt.HasValue) - { - connectionBuilder.Encrypt = connectionDetails.Encrypt.Value; - } - if (connectionDetails.TrustServerCertificate.HasValue) - { - connectionBuilder.TrustServerCertificate = connectionDetails.TrustServerCertificate.Value; - } - if (connectionDetails.PersistSecurityInfo.HasValue) - { - connectionBuilder.PersistSecurityInfo = connectionDetails.PersistSecurityInfo.Value; - } - if (connectionDetails.ConnectTimeout.HasValue) - { - connectionBuilder.ConnectTimeout = connectionDetails.ConnectTimeout.Value; - } - if (connectionDetails.ConnectRetryCount.HasValue) - { - connectionBuilder.ConnectRetryCount = connectionDetails.ConnectRetryCount.Value; - } - if (connectionDetails.ConnectRetryInterval.HasValue) - { - connectionBuilder.ConnectRetryInterval = connectionDetails.ConnectRetryInterval.Value; - } - if (!string.IsNullOrEmpty(connectionDetails.ApplicationName)) - { - connectionBuilder.ApplicationName = connectionDetails.ApplicationName; - } - if (!string.IsNullOrEmpty(connectionDetails.WorkstationId)) - { - connectionBuilder.WorkstationID = connectionDetails.WorkstationId; - } - if (!string.IsNullOrEmpty(connectionDetails.ApplicationIntent)) - { - ApplicationIntent intent; - switch (connectionDetails.ApplicationIntent) - { - case "ReadOnly": - intent = ApplicationIntent.ReadOnly; - break; - case "ReadWrite": - intent = ApplicationIntent.ReadWrite; - break; - default: - throw new ArgumentException(SR.ConnectionServiceConnStringInvalidIntent(connectionDetails.ApplicationIntent)); - } - connectionBuilder.ApplicationIntent = intent; - } - if (!string.IsNullOrEmpty(connectionDetails.CurrentLanguage)) - { - connectionBuilder.CurrentLanguage = connectionDetails.CurrentLanguage; - } - if (connectionDetails.Pooling.HasValue) - { - connectionBuilder.Pooling = connectionDetails.Pooling.Value; - } - if (connectionDetails.MaxPoolSize.HasValue) - { - connectionBuilder.MaxPoolSize = connectionDetails.MaxPoolSize.Value; - } - if (connectionDetails.MinPoolSize.HasValue) - { - connectionBuilder.MinPoolSize = connectionDetails.MinPoolSize.Value; - } - if (connectionDetails.LoadBalanceTimeout.HasValue) - { - connectionBuilder.LoadBalanceTimeout = connectionDetails.LoadBalanceTimeout.Value; - } - if (connectionDetails.Replication.HasValue) - { - connectionBuilder.Replication = connectionDetails.Replication.Value; - } - if (!string.IsNullOrEmpty(connectionDetails.AttachDbFilename)) - { - connectionBuilder.AttachDBFilename = connectionDetails.AttachDbFilename; - } - if (!string.IsNullOrEmpty(connectionDetails.FailoverPartner)) - { - connectionBuilder.FailoverPartner = connectionDetails.FailoverPartner; - } - if (connectionDetails.MultiSubnetFailover.HasValue) - { - connectionBuilder.MultiSubnetFailover = connectionDetails.MultiSubnetFailover.Value; - } - if (connectionDetails.MultipleActiveResultSets.HasValue) - { - connectionBuilder.MultipleActiveResultSets = connectionDetails.MultipleActiveResultSets.Value; - } - if (connectionDetails.PacketSize.HasValue) - { - connectionBuilder.PacketSize = connectionDetails.PacketSize.Value; - } - if (!string.IsNullOrEmpty(connectionDetails.TypeSystemVersion)) - { - connectionBuilder.TypeSystemVersion = connectionDetails.TypeSystemVersion; - } - - return connectionBuilder.ToString(); - } - - /// - /// Change the database context of a connection. - /// - /// URI of the owner of the connection - /// Name of the database to change the connection to - public void ChangeConnectionDatabaseContext(string ownerUri, string newDatabaseName) - { - ConnectionInfo info; - if (TryFindConnection(ownerUri, out info)) - { - try - { - foreach (DbConnection connection in info.AllConnections) - { - if (connection.State == ConnectionState.Open) - { - connection.ChangeDatabase(newDatabaseName); - } - } - - info.ConnectionDetails.DatabaseName = newDatabaseName; - - // Fire a connection changed event - ConnectionChangedParams parameters = new ConnectionChangedParams(); - ConnectionSummary summary = info.ConnectionDetails; - parameters.Connection = summary.Clone(); - parameters.OwnerUri = ownerUri; - ServiceHost.SendEvent(ConnectionChangedNotification.Type, parameters); - } - catch (Exception e) - { - Logger.Write( - LogLevel.Error, - string.Format( - "Exception caught while trying to change database context to [{0}] for OwnerUri [{1}]. Exception:{2}", - newDatabaseName, - ownerUri, - e.ToString()) - ); - } - } - } - - /// - /// Invokes the initial on-connect activities if the provided ConnectParams represents the default - /// connection. - /// - private void InvokeOnConnectionActivities(ConnectionInfo connectionInfo, ConnectParams connectParams) - { - if (connectParams.Type != ConnectionType.Default) - { - return; - } - - foreach (var activity in this.onConnectionActivities) - { - // not awaiting here to allow handlers to run in the background - activity(connectionInfo); - } - } - - /// - /// Invokes the final on-disconnect activities if the provided DisconnectParams represents the default - /// connection or is null - representing that all connections are being disconnected. - /// - private void InvokeOnDisconnectionActivities(ConnectionInfo connectionInfo) - { - foreach (var activity in this.onDisconnectActivities) - { - activity(connectionInfo.ConnectionDetails, connectionInfo.OwnerUri); - } - } - - /// - /// Handles the Telemetry events that occur upon disconnect. - /// - /// - private void HandleDisconnectTelemetry(ConnectionInfo connectionInfo) - { - if (ServiceHost != null) - { - try - { - // Send a telemetry notification for intellisense performance metrics - ServiceHost.SendEvent(TelemetryNotification.Type, new TelemetryParams() - { - Params = new TelemetryProperties - { - Properties = new Dictionary - { - { TelemetryPropertyNames.IsAzure, connectionInfo.IsAzure.ToOneOrZeroString() } - }, - EventName = TelemetryEventNames.IntellisenseQuantile, - Measures = connectionInfo.IntellisenseMetrics.Quantile - } - }); - } - catch (Exception ex) - { - Logger.Write(LogLevel.Verbose, "Could not send Connection telemetry event " + ex.ToString()); - } - } - } - } -} + /// + /// Creates a ConnectionCompleteParams as a response to a successful connection. + /// Also sets the DatabaseName and IsAzure properties of ConnectionInfo. + /// + /// A ConnectionCompleteParams in response to the successful connection + private ConnectionCompleteParams GetConnectionCompleteParams(string connectionType, ConnectionInfo connectionInfo) + { + ConnectionCompleteParams response = new ConnectionCompleteParams { OwnerUri = connectionInfo.OwnerUri, Type = connectionType }; + + try + { + DbConnection connection; + connectionInfo.TryGetConnection(connectionType, out connection); + + // Update with the actual database name in connectionInfo and result + // Doing this here as we know the connection is open - expect to do this only on connecting + connectionInfo.ConnectionDetails.DatabaseName = connection.Database; + response.ConnectionSummary = new ConnectionSummary + { + ServerName = connectionInfo.ConnectionDetails.ServerName, + DatabaseName = connectionInfo.ConnectionDetails.DatabaseName, + UserName = connectionInfo.ConnectionDetails.UserName, + }; + + response.ConnectionId = connectionInfo.ConnectionId.ToString(); + + var reliableConnection = connection as ReliableSqlConnection; + DbConnection underlyingConnection = reliableConnection != null + ? reliableConnection.GetUnderlyingConnection() + : connection; + + ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(underlyingConnection); + response.ServerInfo = new ServerInfo + { + ServerMajorVersion = serverInfo.ServerMajorVersion, + ServerMinorVersion = serverInfo.ServerMinorVersion, + ServerReleaseVersion = serverInfo.ServerReleaseVersion, + EngineEditionId = serverInfo.EngineEditionId, + ServerVersion = serverInfo.ServerVersion, + ServerLevel = serverInfo.ServerLevel, + ServerEdition = serverInfo.ServerEdition, + IsCloud = serverInfo.IsCloud, + AzureVersion = serverInfo.AzureVersion, + OsVersion = serverInfo.OsVersion + }; + connectionInfo.IsAzure = serverInfo.IsCloud; + connectionInfo.MajorVersion = serverInfo.ServerMajorVersion; + connectionInfo.IsSqlDW = (serverInfo.EngineEditionId == (int)DatabaseEngineEdition.SqlDataWarehouse); + } + catch (Exception ex) + { + response.Messages = ex.ToString(); + } + + return response; + } + + /// + /// Tries to create and open a connection with the given ConnectParams. + /// + /// null upon success, a ConnectionCompleteParams detailing the error upon failure + private async Task TryOpenConnection(ConnectionInfo connectionInfo, ConnectParams connectionParams) + { + CancellationTokenSource source = null; + DbConnection connection = null; + CancelTokenKey cancelKey = new CancelTokenKey { OwnerUri = connectionParams.OwnerUri, Type = connectionParams.Type }; + ConnectionCompleteParams response = new ConnectionCompleteParams { OwnerUri = connectionInfo.OwnerUri, Type = connectionParams.Type }; + + try + { + // build the connection string from the input parameters + string connectionString = BuildConnectionString(connectionInfo.ConnectionDetails); + + // create a sql connection instance + connection = connectionInfo.Factory.CreateSqlConnection(connectionString); + connectionInfo.AddConnection(connectionParams.Type, connection); + + // Add a cancellation token source so that the connection OpenAsync() can be cancelled + source = new CancellationTokenSource(); + // Locking here to perform two operations as one atomic operation + lock (cancellationTokenSourceLock) + { + // If the URI is currently connecting from a different request, cancel it before we try to connect + CancellationTokenSource currentSource; + if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out currentSource)) + { + currentSource.Cancel(); + } + cancelTupleToCancellationTokenSourceMap[cancelKey] = source; + } + + // Open the connection + await connection.OpenAsync(source.Token); + } + catch (SqlException ex) + { + response.ErrorNumber = ex.Number; + response.ErrorMessage = ex.Message; + response.Messages = ex.ToString(); + return response; + } + catch (OperationCanceledException) + { + // OpenAsync was cancelled + response.Messages = SR.ConnectionServiceConnectionCanceled; + return response; + } + catch (Exception ex) + { + response.ErrorMessage = ex.Message; + response.Messages = ex.ToString(); + return response; + } + finally + { + // Remove our cancellation token from the map since we're no longer connecting + // Using a lock here to perform two operations as one atomic operation + lock (cancellationTokenSourceLock) + { + // Only remove the token from the map if it is the same one created by this request + CancellationTokenSource sourceValue; + if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out sourceValue) && sourceValue == source) + { + cancelTupleToCancellationTokenSourceMap.TryRemove(cancelKey, out sourceValue); + } + source?.Dispose(); + } + } + + // Return null upon success + return null; + } + + /// + /// Gets the existing connection with the given URI and connection type string. If none exists, + /// creates a new connection. This cannot be used to create a default connection or to create a + /// connection if a default connection does not exist. + /// + /// A DB connection for the connection type requested + public async Task GetOrOpenConnection(string ownerUri, string connectionType) + { + Validate.IsNotNullOrEmptyString(nameof(ownerUri), ownerUri); + Validate.IsNotNullOrEmptyString(nameof(connectionType), connectionType); + + // Try to get the ConnectionInfo, if it exists + ConnectionInfo connectionInfo; + if (!ownerToConnectionMap.TryGetValue(ownerUri, out connectionInfo)) + { + throw new ArgumentOutOfRangeException(SR.ConnectionServiceListDbErrorNotConnected(ownerUri)); + } + + // Make sure a default connection exists + DbConnection defaultConnection; + if (!connectionInfo.TryGetConnection(ConnectionType.Default, out defaultConnection)) + { + throw new InvalidOperationException(SR.ConnectionServiceDbErrorDefaultNotConnected(ownerUri)); + } + + // Try to get the DbConnection + DbConnection connection; + if (!connectionInfo.TryGetConnection(connectionType, out connection) && ConnectionType.Default != connectionType) + { + // If the DbConnection does not exist and is not the default connection, create one. + // We can't create the default (initial) connection here because we won't have a ConnectionDetails + // if Connect() has not yet been called. + ConnectParams connectParams = new ConnectParams + { + OwnerUri = ownerUri, + Connection = connectionInfo.ConnectionDetails, + Type = connectionType + }; + await Connect(connectParams); + connectionInfo.TryGetConnection(connectionType, out connection); + } + + return connection; + } + + /// + /// Cancel a connection that is in the process of opening. + /// + public bool CancelConnect(CancelConnectParams cancelParams) + { + // Validate parameters + if (cancelParams == null || string.IsNullOrEmpty(cancelParams.OwnerUri)) + { + return false; + } + + CancelTokenKey cancelKey = new CancelTokenKey + { + OwnerUri = cancelParams.OwnerUri, + Type = cancelParams.Type + }; + + // Cancel any current connection attempts for this URI + CancellationTokenSource source; + if (cancelTupleToCancellationTokenSourceMap.TryGetValue(cancelKey, out source)) + { + try + { + source.Cancel(); + return true; + } + catch + { + return false; + } + } + + return false; + } + + /// + /// Close a connection with the specified connection details. + /// + public virtual bool Disconnect(DisconnectParams disconnectParams) + { + // Validate parameters + if (disconnectParams == null || string.IsNullOrEmpty(disconnectParams.OwnerUri)) + { + return false; + } + + // Cancel if we are in the middle of connecting + if (CancelConnections(disconnectParams.OwnerUri, disconnectParams.Type)) + { + return false; + } + + // Lookup the ConnectionInfo owned by the URI + ConnectionInfo info; + if (!ownerToConnectionMap.TryGetValue(disconnectParams.OwnerUri, out info)) + { + return false; + } + + // Call Close() on the connections we want to disconnect + // If no connections were located, return false + if (!CloseConnections(info, disconnectParams.Type)) + { + return false; + } + + // Remove the disconnected connections from the ConnectionInfo map + if (disconnectParams.Type == null) + { + info.RemoveAllConnections(); + } + else + { + info.RemoveConnection(disconnectParams.Type); + } + + // If the ConnectionInfo has no more connections, remove the ConnectionInfo + if (info.CountConnections == 0) + { + ownerToConnectionMap.Remove(disconnectParams.OwnerUri); + } + + // Handle Telemetry disconnect events if we are disconnecting the default connection + if (disconnectParams.Type == null || disconnectParams.Type == ConnectionType.Default) + { + HandleDisconnectTelemetry(info); + InvokeOnDisconnectionActivities(info); + } + + // Return true upon success + return true; + } + + /// + /// Cancel connections associated with the given ownerUri. + /// If connectionType is not null, cancel the connection with the given connectionType + /// If connectionType is null, cancel all pending connections associated with ownerUri. + /// + /// true if a single pending connection associated with the non-null connectionType was + /// found and cancelled, false otherwise + private bool CancelConnections(string ownerUri, string connectionType) + { + // Cancel the connection of the given type + if (connectionType != null) + { + // If we are trying to disconnect a specific connection and it was just cancelled, + // this will return true + return CancelConnect(new CancelConnectParams() { OwnerUri = ownerUri, Type = connectionType }); + } + + // Cancel all pending connections + foreach (var entry in cancelTupleToCancellationTokenSourceMap) + { + string entryConnectionUri = entry.Key.OwnerUri; + string entryConnectionType = entry.Key.Type; + if (ownerUri.Equals(entryConnectionUri)) + { + CancelConnect(new CancelConnectParams() { OwnerUri = ownerUri, Type = entryConnectionType }); + } + } + + return false; + } + + /// + /// Closes DbConnections associated with the given ConnectionInfo. + /// If connectionType is not null, closes the DbConnection with the type given by connectionType. + /// If connectionType is null, closes all DbConnections. + /// + /// true if connections were found and attempted to be closed, + /// false if no connections were found + private bool CloseConnections(ConnectionInfo connectionInfo, string connectionType) + { + ICollection connectionsToDisconnect = new List(); + if (connectionType == null) + { + connectionsToDisconnect = connectionInfo.AllConnections; + } + else + { + // Make sure there is an existing connection of this type + DbConnection connection; + if (!connectionInfo.TryGetConnection(connectionType, out connection)) + { + return false; + } + connectionsToDisconnect.Add(connection); + } + + if (connectionsToDisconnect.Count == 0) + { + return false; + } + + foreach (DbConnection connection in connectionsToDisconnect) + { + try + { + connection.Close(); + } + catch (Exception) + { + // Ignore + } + } + + return true; + } + + /// + /// List all databases on the server specified + /// + public ListDatabasesResponse ListDatabases(ListDatabasesParams listDatabasesParams) + { + // Verify parameters + var owner = listDatabasesParams.OwnerUri; + if (string.IsNullOrEmpty(owner)) + { + throw new ArgumentException(SR.ConnectionServiceListDbErrorNullOwnerUri); + } + + // Use the existing connection as a base for the search + ConnectionInfo info; + if (!TryFindConnection(owner, out info)) + { + throw new Exception(SR.ConnectionServiceListDbErrorNotConnected(owner)); + } + ConnectionDetails connectionDetails = info.ConnectionDetails.Clone(); + + // Connect to master and query sys.databases + connectionDetails.DatabaseName = "master"; + var connection = this.ConnectionFactory.CreateSqlConnection(BuildConnectionString(connectionDetails)); + connection.Open(); + + List results = new List(); + var systemDatabases = new[] {"master", "model", "msdb", "tempdb"}; + using (DbCommand command = connection.CreateCommand()) + { + command.CommandText = "SELECT name FROM sys.databases ORDER BY name ASC"; + command.CommandTimeout = 15; + command.CommandType = CommandType.Text; + + using (var reader = command.ExecuteReader()) + { + while (reader.Read()) + { + results.Add(reader[0].ToString()); + } + } + } + + // Put system databases at the top of the list + results = + results.Where(s => systemDatabases.Any(s.Equals)).Concat( + results.Where(s => systemDatabases.All(x => !s.Equals(x)))).ToList(); + + connection.Close(); + + ListDatabasesResponse response = new ListDatabasesResponse(); + response.DatabaseNames = results.ToArray(); + + return response; + } + + public void InitializeService(IProtocolEndpoint serviceHost) + { + this.ServiceHost = serviceHost; + + // Register request and event handlers with the Service Host + serviceHost.SetRequestHandler(ConnectionRequest.Type, HandleConnectRequest); + serviceHost.SetRequestHandler(CancelConnectRequest.Type, HandleCancelConnectRequest); + serviceHost.SetRequestHandler(DisconnectRequest.Type, HandleDisconnectRequest); + serviceHost.SetRequestHandler(ListDatabasesRequest.Type, HandleListDatabasesRequest); + + // Register the configuration update handler + WorkspaceService.Instance.RegisterConfigChangeCallback(HandleDidChangeConfigurationNotification); + } + + /// + /// Add a new method to be called when the onconnection request is submitted + /// + /// + public void RegisterOnConnectionTask(OnConnectionHandler activity) + { + onConnectionActivities.Add(activity); + } + + /// + /// Add a new method to be called when the ondisconnect request is submitted + /// + public void RegisterOnDisconnectTask(OnDisconnectHandler activity) + { + onDisconnectActivities.Add(activity); + } + + /// + /// Handle new connection requests + /// + /// + /// + /// + protected async Task HandleConnectRequest( + ConnectParams connectParams, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleConnectRequest"); + + try + { + RunConnectRequestHandlerTask(connectParams); + await requestContext.SendResult(true); + } + catch + { + await requestContext.SendResult(false); + } + } + + private void RunConnectRequestHandlerTask(ConnectParams connectParams) + { + // create a task to connect asynchronously so that other requests are not blocked in the meantime + Task.Run(async () => + { + try + { + // result is null if the ConnectParams was successfully validated + ConnectionCompleteParams result = ValidateConnectParams(connectParams); + if (result != null) + { + await ServiceHost.SendEvent(ConnectionCompleteNotification.Type, result); + return; + } + + // open connection based on request details + result = await Connect(connectParams); + await ServiceHost.SendEvent(ConnectionCompleteNotification.Type, result); + } + catch (Exception ex) + { + ConnectionCompleteParams result = new ConnectionCompleteParams() + { + Messages = ex.ToString() + }; + await ServiceHost.SendEvent(ConnectionCompleteNotification.Type, result); + } + }); + } + + /// + /// Handle cancel connect requests + /// + protected async Task HandleCancelConnectRequest( + CancelConnectParams cancelParams, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleCancelConnectRequest"); + + try + { + bool result = CancelConnect(cancelParams); + await requestContext.SendResult(result); + } + catch(Exception ex) + { + await requestContext.SendError(ex.ToString()); + } + } + + /// + /// Handle disconnect requests + /// + protected async Task HandleDisconnectRequest( + DisconnectParams disconnectParams, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "HandleDisconnectRequest"); + + try + { + bool result = Instance.Disconnect(disconnectParams); + await requestContext.SendResult(result); + } + catch(Exception ex) + { + await requestContext.SendError(ex.ToString()); + } + + } + + /// + /// Handle requests to list databases on the current server + /// + protected async Task HandleListDatabasesRequest( + ListDatabasesParams listDatabasesParams, + RequestContext requestContext) + { + Logger.Write(LogLevel.Verbose, "ListDatabasesRequest"); + + try + { + ListDatabasesResponse result = Instance.ListDatabases(listDatabasesParams); + await requestContext.SendResult(result); + } + catch(Exception ex) + { + await requestContext.SendError(ex.ToString()); + } + } + + public Task HandleDidChangeConfigurationNotification( + SqlToolsSettings newSettings, + SqlToolsSettings oldSettings, + EventContext eventContext) + { + return Task.FromResult(true); + } + + /// + /// Build a connection string from a connection details instance + /// + /// + public static string BuildConnectionString(ConnectionDetails connectionDetails) + { + SqlConnectionStringBuilder connectionBuilder = new SqlConnectionStringBuilder + { + ["Data Source"] = connectionDetails.ServerName, + ["User Id"] = connectionDetails.UserName, + ["Password"] = connectionDetails.Password + }; + + // Check for any optional parameters + if (!string.IsNullOrEmpty(connectionDetails.DatabaseName)) + { + connectionBuilder["Initial Catalog"] = connectionDetails.DatabaseName; + } + if (!string.IsNullOrEmpty(connectionDetails.AuthenticationType)) + { + switch(connectionDetails.AuthenticationType) + { + case "Integrated": + connectionBuilder.IntegratedSecurity = true; + break; + case "SqlLogin": + break; + default: + throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAuthType(connectionDetails.AuthenticationType)); + } + } + if (connectionDetails.Encrypt.HasValue) + { + connectionBuilder.Encrypt = connectionDetails.Encrypt.Value; + } + if (connectionDetails.TrustServerCertificate.HasValue) + { + connectionBuilder.TrustServerCertificate = connectionDetails.TrustServerCertificate.Value; + } + if (connectionDetails.PersistSecurityInfo.HasValue) + { + connectionBuilder.PersistSecurityInfo = connectionDetails.PersistSecurityInfo.Value; + } + if (connectionDetails.ConnectTimeout.HasValue) + { + connectionBuilder.ConnectTimeout = connectionDetails.ConnectTimeout.Value; + } + if (connectionDetails.ConnectRetryCount.HasValue) + { + connectionBuilder.ConnectRetryCount = connectionDetails.ConnectRetryCount.Value; + } + if (connectionDetails.ConnectRetryInterval.HasValue) + { + connectionBuilder.ConnectRetryInterval = connectionDetails.ConnectRetryInterval.Value; + } + if (!string.IsNullOrEmpty(connectionDetails.ApplicationName)) + { + connectionBuilder.ApplicationName = connectionDetails.ApplicationName; + } + if (!string.IsNullOrEmpty(connectionDetails.WorkstationId)) + { + connectionBuilder.WorkstationID = connectionDetails.WorkstationId; + } + if (!string.IsNullOrEmpty(connectionDetails.ApplicationIntent)) + { + ApplicationIntent intent; + switch (connectionDetails.ApplicationIntent) + { + case "ReadOnly": + intent = ApplicationIntent.ReadOnly; + break; + case "ReadWrite": + intent = ApplicationIntent.ReadWrite; + break; + default: + throw new ArgumentException(SR.ConnectionServiceConnStringInvalidIntent(connectionDetails.ApplicationIntent)); + } + connectionBuilder.ApplicationIntent = intent; + } + if (!string.IsNullOrEmpty(connectionDetails.CurrentLanguage)) + { + connectionBuilder.CurrentLanguage = connectionDetails.CurrentLanguage; + } + if (connectionDetails.Pooling.HasValue) + { + connectionBuilder.Pooling = connectionDetails.Pooling.Value; + } + if (connectionDetails.MaxPoolSize.HasValue) + { + connectionBuilder.MaxPoolSize = connectionDetails.MaxPoolSize.Value; + } + if (connectionDetails.MinPoolSize.HasValue) + { + connectionBuilder.MinPoolSize = connectionDetails.MinPoolSize.Value; + } + if (connectionDetails.LoadBalanceTimeout.HasValue) + { + connectionBuilder.LoadBalanceTimeout = connectionDetails.LoadBalanceTimeout.Value; + } + if (connectionDetails.Replication.HasValue) + { + connectionBuilder.Replication = connectionDetails.Replication.Value; + } + if (!string.IsNullOrEmpty(connectionDetails.AttachDbFilename)) + { + connectionBuilder.AttachDBFilename = connectionDetails.AttachDbFilename; + } + if (!string.IsNullOrEmpty(connectionDetails.FailoverPartner)) + { + connectionBuilder.FailoverPartner = connectionDetails.FailoverPartner; + } + if (connectionDetails.MultiSubnetFailover.HasValue) + { + connectionBuilder.MultiSubnetFailover = connectionDetails.MultiSubnetFailover.Value; + } + if (connectionDetails.MultipleActiveResultSets.HasValue) + { + connectionBuilder.MultipleActiveResultSets = connectionDetails.MultipleActiveResultSets.Value; + } + if (connectionDetails.PacketSize.HasValue) + { + connectionBuilder.PacketSize = connectionDetails.PacketSize.Value; + } + if (!string.IsNullOrEmpty(connectionDetails.TypeSystemVersion)) + { + connectionBuilder.TypeSystemVersion = connectionDetails.TypeSystemVersion; + } + + return connectionBuilder.ToString(); + } + + /// + /// Change the database context of a connection. + /// + /// URI of the owner of the connection + /// Name of the database to change the connection to + public void ChangeConnectionDatabaseContext(string ownerUri, string newDatabaseName) + { + ConnectionInfo info; + if (TryFindConnection(ownerUri, out info)) + { + try + { + foreach (DbConnection connection in info.AllConnections) + { + if (connection.State == ConnectionState.Open) + { + connection.ChangeDatabase(newDatabaseName); + } + } + + info.ConnectionDetails.DatabaseName = newDatabaseName; + + // Fire a connection changed event + ConnectionChangedParams parameters = new ConnectionChangedParams(); + ConnectionSummary summary = info.ConnectionDetails; + parameters.Connection = summary.Clone(); + parameters.OwnerUri = ownerUri; + ServiceHost.SendEvent(ConnectionChangedNotification.Type, parameters); + } + catch (Exception e) + { + Logger.Write( + LogLevel.Error, + string.Format( + "Exception caught while trying to change database context to [{0}] for OwnerUri [{1}]. Exception:{2}", + newDatabaseName, + ownerUri, + e.ToString()) + ); + } + } + } + + /// + /// Invokes the initial on-connect activities if the provided ConnectParams represents the default + /// connection. + /// + private void InvokeOnConnectionActivities(ConnectionInfo connectionInfo, ConnectParams connectParams) + { + if (connectParams.Type != ConnectionType.Default) + { + return; + } + + foreach (var activity in this.onConnectionActivities) + { + // not awaiting here to allow handlers to run in the background + activity(connectionInfo); + } + } + + /// + /// Invokes the final on-disconnect activities if the provided DisconnectParams represents the default + /// connection or is null - representing that all connections are being disconnected. + /// + private void InvokeOnDisconnectionActivities(ConnectionInfo connectionInfo) + { + foreach (var activity in this.onDisconnectActivities) + { + activity(connectionInfo.ConnectionDetails, connectionInfo.OwnerUri); + } + } + + /// + /// Handles the Telemetry events that occur upon disconnect. + /// + /// + private void HandleDisconnectTelemetry(ConnectionInfo connectionInfo) + { + if (ServiceHost != null) + { + try + { + // Send a telemetry notification for intellisense performance metrics + ServiceHost.SendEvent(TelemetryNotification.Type, new TelemetryParams() + { + Params = new TelemetryProperties + { + Properties = new Dictionary + { + { TelemetryPropertyNames.IsAzure, connectionInfo.IsAzure.ToOneOrZeroString() } + }, + EventName = TelemetryEventNames.IntellisenseQuantile, + Measures = connectionInfo.IntellisenseMetrics.Quantile + } + }); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Verbose, "Could not send Connection telemetry event " + ex.ToString()); + } + } + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/CloseSessionRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/CloseSessionRequest.cs new file mode 100644 index 00000000..d583555f --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/CloseSessionRequest.cs @@ -0,0 +1,53 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts +{ + /// + /// Information returned from a . + /// Contains success information, a to be used when + /// requesting closing an existing session. + /// + public class CloseSessionResponse + { + /// + /// Boolean indicating if the session was closed successfully + /// + public bool Success { get; set; } + + /// + /// Unique ID to use when sending any requests for objects in the + /// tree under the node + /// + public string SessionId { get; set; } + } + + /// + /// Parameters to the . + /// + public class CloseSessionParams + { + /// + /// The Id returned from a . This + /// is used to disambiguate between different trees. + /// + public string SessionId { get; set; } + } + + /// + /// Establishes an Object Explorer tree session for a specific connection. + /// This will create a connection to a specific server or database, register + /// it for use in the + /// + public class CloseSessionRequest + { + public static readonly + RequestType Type = + RequestType.Create("objectexplorer/closesession"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/RefreshRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/RefreshRequest.cs index 74cfc8ed..c9974c6f 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/RefreshRequest.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Contracts/RefreshRequest.cs @@ -1,39 +1,56 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + using Microsoft.SqlTools.Hosting.Protocol.Contracts; - -namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts -{ - /// - /// Parameters to the . - /// - public class RefreshParams - { - /// - /// The Id returned from a . This - /// is used to disambiguate between different trees. - /// - public string SessionId { get; set; } - - /// - /// Path identifying the node to expand. See for details - /// - public string[] NodePath { get; set; } - } - - /// - /// A request to expand a - /// - public class RefreshRequest - { - /// - /// Returns children of a given node as a array. - /// - public static readonly - RequestType Type = - RequestType.Create("objectexplorer/refresh"); - } -} + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts +{ + /// + /// Information returned from a . + /// + public class RefreshResponse + { + /// + /// Unique ID to use when sending any requests for objects in the + /// tree under the node + /// + public string SessionId { get; set; } + + /// + /// Information describing the expanded nodes in the tree + /// + public NodeInfo[] Nodes { get; set; } + } + + /// + /// Parameters to the . + /// + public class RefreshParams + { + /// + /// The Id returned from a . This + /// is used to disambiguate between different trees. + /// + public string SessionId { get; set; } + + /// + /// Path identifying the node to refresh. See for details + /// + public string NodePath { get; set; } + } + + /// + /// A request to expand a + /// + public class RefreshRequest + { + /// + /// Returns children of a given node as a array. + /// + public static readonly + RequestType Type = + RequestType.Create("objectexplorer/refresh"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeFilter.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeFilter.cs index 72b0dc99..cfaea0c3 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeFilter.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/NodeFilter.cs @@ -74,7 +74,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes { proeprtyValue = (int)Convert.ChangeType(value, Type); } - string orPrefix = i == 0 ? "" : "or"; + string orPrefix = i == 0 ? string.Empty : "or"; filter = $"{filter} {orPrefix} @{Property} = {proeprtyValue}"; } } @@ -91,8 +91,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes { var value = list[i]; - string orPrefix = i == 0 ? "" : "and"; - filter = $"{filter} {orPrefix} {value.ToPropertyFilterString()}"; + string andPrefix = i == 0 ? string.Empty : "and"; + filter = $"{filter} {andPrefix} {value.ToPropertyFilterString()}"; } filter = $"[{filter}]"; diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs index 4c2b2c9a..cd0c0c9e 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/Nodes/TreeNode.cs @@ -195,6 +195,17 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes return children; } + /// + /// Refresh this node and returns its children + /// + /// Children as an IList. This is the raw children collection, not a copy + public IList Refresh() + { + // TODO consider why solution explorer has separate Children and Items options + PopulateChildren(); + return children; + } + /// /// Gets a readonly view of the currently defined children for this node. /// This does not expand the node at all @@ -242,7 +253,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes { return Parent as T; } - + protected void PopulateChildren() { Debug.Assert(IsAlwaysLeaf == false); diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs index 8587bed0..1e7ba342 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/ObjectExplorerService.cs @@ -4,7 +4,9 @@ // using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Composition; using System.Globalization; using System.Linq; @@ -33,7 +35,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer // Instance of the connection service, used to get the connection info for a given owner URI private ConnectionService connectionService; private IProtocolEndpoint serviceHost; - private Dictionary sessionMap; + private ConcurrentDictionary sessionMap; private readonly Lazy>> applicableNodeChildFactories; private IMultiServiceProvider serviceProvider; @@ -42,7 +44,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer /// public ObjectExplorerService() { - sessionMap = new Dictionary(); + sessionMap = new ConcurrentDictionary(); applicableNodeChildFactories = new Lazy>>(() => PopulateFactories()); } @@ -62,6 +64,17 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer return applicableNodeChildFactories.Value; } } + + /// + /// Returns the session ids + /// + internal IReadOnlyCollection SessionIds + { + get + { + return new ReadOnlyCollection(sessionMap.Keys.ToList()); + } + } /// /// As an , this will be set whenever the service is initialized @@ -86,6 +99,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer // Register handlers for requests serviceHost.SetRequestHandler(CreateSessionRequest.Type, HandleCreateSessionRequest); serviceHost.SetRequestHandler(ExpandRequest.Type, HandleExpandRequest); + serviceHost.SetRequestHandler(RefreshRequest.Type, HandleRefreshRequest); + serviceHost.SetRequestHandler(CloseSessionRequest.Type, HandleCloseSessionRequest); } public void CloseSession(string uri) @@ -94,7 +109,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer if (sessionMap.TryGetValue(uri, out session)) { // Establish a connection to the specified server/database - sessionMap.Remove(session.Uri); + sessionMap.TryRemove(session.Uri, out session); + connectionService.Disconnect(new DisconnectParams() + { + OwnerUri = uri + }); } } @@ -136,7 +155,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer await HandleRequestAsync(doCreateSession, context, "HandleCreateSessionRequest"); } - internal async Task ExpandNode(ObjectExplorerSession session, string nodePath) + internal async Task ExpandNode(ObjectExplorerSession session, string nodePath, bool forceRefresh = false) { return await Task.Factory.StartNew(() => { @@ -144,7 +163,14 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer TreeNode node = session.Root.FindNodeByPath(nodePath); if(node != null) { - nodes = node.Expand().Select(x => x.ToNodeInfo()).ToArray(); + if (forceRefresh) + { + nodes = node.Refresh().Select(x => x.ToNodeInfo()).ToArray(); + } + else + { + nodes = node.Expand().Select(x => x.ToNodeInfo()).ToArray(); + } } return nodes; }); @@ -167,7 +193,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer } session = ObjectExplorerSession.CreateSession(connectionResult, serviceProvider); - sessionMap[uri] = session; + sessionMap.AddOrUpdate(uri, session, (key, oldSession) => session); return session; } @@ -212,30 +238,87 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer string uri = expandParams.SessionId; ObjectExplorerSession session = null; NodeInfo[] nodes = null; - if (sessionMap.ContainsKey(uri)) + ExpandResponse response; + if (!sessionMap.TryGetValue(uri, out session)) { - session = sessionMap[uri]; - } - else - { - //TODO: error + Logger.Write(LogLevel.Verbose, $"Cannot expand object explorer node. Couldn't find session for uri. {uri} "); } - if (session != null) { - // Establish a connection to the specified server/database + // expand the nodes for given node path nodes = await ExpandNode(session, expandParams.NodePath); } - ExpandResponse response; response = new ExpandResponse() { Nodes = nodes, SessionId = uri }; return response; }; await HandleRequestAsync(expandNode, context, "HandleExpandRequest"); } - + + internal async Task HandleRefreshRequest(RefreshParams refreshParams, RequestContext context) + { + Logger.Write(LogLevel.Verbose, "HandleRefreshRequest"); + Func> refreshNode = async () => + { + Validate.IsNotNull(nameof(refreshParams), refreshParams); + Validate.IsNotNull(nameof(context), context); + + string uri = refreshParams.SessionId; + ObjectExplorerSession session = null; + NodeInfo[] nodes = null; + RefreshResponse response; + if (!sessionMap.TryGetValue(uri, out session)) + { + Logger.Write(LogLevel.Verbose, $"Cannot refresh object explorer node. Couldn't find session for uri. {uri} "); + } + + if (session != null) + { + // refresh the nodes for given node path + nodes = await ExpandNode(session, refreshParams.NodePath, true); + } + + response = new RefreshResponse() { Nodes = nodes, SessionId = uri }; + return response; + }; + + await HandleRequestAsync(refreshNode, context, "HandleRefreshRequest"); + } + + internal async Task HandleCloseSessionRequest(CloseSessionParams closeSessionParams, RequestContext context) + { + Validate.IsNotNull(nameof(closeSessionParams), closeSessionParams); + Validate.IsNotNull(nameof(context), context); + Logger.Write(LogLevel.Verbose, "HandleCloseSessionRequest"); + Func> closeSession = () => + { + return Task.Factory.StartNew(() => + { + string uri = closeSessionParams.SessionId; + ObjectExplorerSession session = null; + bool success = false; + if (!sessionMap.TryGetValue(uri, out session)) + { + Logger.Write(LogLevel.Verbose, $"Cannot close object explorer session. Couldn't find session for uri. {uri} "); + } + + if (session != null) + { + // refresh the nodes for given node path + CloseSession(uri); + success = true; + } + + var response = new CloseSessionResponse() {Success = success, SessionId = uri}; + return response; + }); + }; + + await HandleRequestAsync(closeSession, context, "HandleCloseSessionRequest"); + } + private async Task HandleRequestAsync(Func> handler, RequestContext requestContext, string requestType) { Logger.Write(LogLevel.Verbose, requestType); diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs index 0f744a90..c117ede7 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs @@ -26,20 +26,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.Databases; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/Database" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.Databases; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/Database" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -66,20 +66,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.LinkedServers; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/LinkedServer" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.LinkedServers; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/LinkedServer" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -106,20 +106,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.Logins; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/Login" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.Logins; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/Login" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -146,20 +146,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.Roles; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/ServerRole" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.Roles; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/ServerRole" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -186,20 +186,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.Credentials; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/Credential" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.Credentials; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/Credential" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -226,20 +226,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.CryptographicProviders; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/CryptographicProvider" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.CryptographicProviders; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/CryptographicProvider" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -266,20 +266,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.Audits; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/Audit" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.Audits; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/Audit" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -306,20 +306,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.ServerAuditSpecifications; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/ServerAuditSpecification" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.ServerAuditSpecifications; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/ServerAuditSpecification" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -346,20 +346,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.Endpoints; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/Endpoint" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.Endpoints; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/Endpoint" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -386,20 +386,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.LinkedServers; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/LinkedServer" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.LinkedServers; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/LinkedServer" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -426,20 +426,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.Triggers; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/ServerDdlTrigger" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.Triggers; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/ServerDdlTrigger" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -466,20 +466,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Server parentServer = context.Parent as Server; if (parentServer != null) { - var retValue = parentServer.UserDefinedMessages; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServer.Urn.ToString()}/UserDefinedMessage" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServer.UserDefinedMessages; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServer.Urn.ToString()}/UserDefinedMessage" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -506,20 +506,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Tables; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/Table" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Tables; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/Table" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -546,20 +546,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Views; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/View" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Views; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/View" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -586,20 +586,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Synonyms; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/Synonym" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Synonyms; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/Synonym" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -626,20 +626,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel TableViewTableTypeBase parentTableViewTableTypeBase = context.Parent as TableViewTableTypeBase; if (parentTableViewTableTypeBase != null) { - var retValue = parentTableViewTableTypeBase.Columns; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentTableViewTableTypeBase.Urn.ToString()}/Column" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentTableViewTableTypeBase.Columns; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentTableViewTableTypeBase.Urn.ToString()}/Column" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -666,20 +666,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel TableViewTableTypeBase parentTableViewTableTypeBase = context.Parent as TableViewTableTypeBase; if (parentTableViewTableTypeBase != null) { - var retValue = parentTableViewTableTypeBase.Indexes; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentTableViewTableTypeBase.Urn.ToString()}/Index" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentTableViewTableTypeBase.Indexes; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentTableViewTableTypeBase.Urn.ToString()}/Index" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -706,20 +706,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Table parentTable = context.Parent as Table; if (parentTable != null) { - var retValue = parentTable.Checks; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentTable.Urn.ToString()}/Check" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentTable.Checks; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentTable.Urn.ToString()}/Check" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -746,20 +746,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Table parentTable = context.Parent as Table; if (parentTable != null) { - var retValue = parentTable.ForeignKeys; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentTable.Urn.ToString()}/ForeignKey" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentTable.ForeignKeys; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentTable.Urn.ToString()}/ForeignKey" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -786,18 +786,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Column parentColumn = context.Parent as Column; if (parentColumn != null) { - var retValue = parentColumn.DefaultConstraint; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentColumn.Urn.ToString()}/DefaultConstraint" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentColumn.DefaultConstraint; if (retValue != null) { return new SqlSmoObject[] { retValue }; @@ -819,20 +809,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Table parentTable = context.Parent as Table; if (parentTable != null) { - var retValue = parentTable.Triggers; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentTable.Urn.ToString()}/Trigger" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentTable.Triggers; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentTable.Urn.ToString()}/Trigger" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -859,18 +849,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Table parentTable = context.Parent as Table; if (parentTable != null) { - var retValue = parentTable.FullTextIndex; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentTable.Urn.ToString()}/FullTextIndex" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentTable.FullTextIndex; if (retValue != null) { return new SqlSmoObject[] { retValue }; @@ -892,20 +872,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel TableViewBase parentTableViewBase = context.Parent as TableViewBase; if (parentTableViewBase != null) { - var retValue = parentTableViewBase.Statistics; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentTableViewBase.Urn.ToString()}/Statistic" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentTableViewBase.Statistics; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentTableViewBase.Urn.ToString()}/Statistic" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -932,20 +912,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Triggers; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/DatabaseDdlTrigger" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Triggers; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/DatabaseDdlTrigger" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -972,20 +952,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Assemblies; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/SqlAssembly" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Assemblies; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/SqlAssembly" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1012,20 +992,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Rules; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/Rule" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Rules; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/Rule" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1052,20 +1032,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Defaults; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/Default" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Defaults; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/Default" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1092,20 +1072,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Sequences; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/Sequence" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Sequences; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/Sequence" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1132,20 +1112,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.UserDefinedDataTypes; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedDataType" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.UserDefinedDataTypes; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedDataType" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1172,20 +1152,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.UserDefinedTableTypes; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedTableType" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.UserDefinedTableTypes; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedTableType" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1212,20 +1192,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.XmlSchemaCollections; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/XmlSchemaCollection" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.XmlSchemaCollections; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/XmlSchemaCollection" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1252,20 +1232,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.UserDefinedTypes; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedType" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.UserDefinedTypes; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedType" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1292,20 +1272,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.UserDefinedFunctions; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedFunction" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.UserDefinedFunctions; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedFunction" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1332,20 +1312,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.UserDefinedAggregates; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedAggregate" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.UserDefinedAggregates; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/UserDefinedAggregate" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1372,20 +1352,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.FileGroups; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/FileGroup" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.FileGroups; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/FileGroup" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1412,20 +1392,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel FileGroup parentFileGroup = context.Parent as FileGroup; if (parentFileGroup != null) { - var retValue = parentFileGroup.Files; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentFileGroup.Urn.ToString()}/DataFile" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentFileGroup.Files; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentFileGroup.Urn.ToString()}/DataFile" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1452,20 +1432,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.FullTextCatalogs; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/FullTextCatalog" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.FullTextCatalogs; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/FullTextCatalog" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1492,20 +1472,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.FullTextStopLists; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/FullTextStopList" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.FullTextStopLists; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/FullTextStopList" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1532,20 +1512,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.PartitionFunctions; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/PartitionFunction" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.PartitionFunctions; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/PartitionFunction" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1572,20 +1552,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.PartitionSchemes; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/PartitionScheme" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.PartitionSchemes; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/PartitionScheme" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1612,20 +1592,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.SearchPropertyLists; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/SearchPropertyList" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.SearchPropertyLists; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/SearchPropertyList" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1652,20 +1632,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Users; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/User" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Users; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/User" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1692,20 +1672,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Schemas; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/Schema" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Schemas; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/Schema" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1732,20 +1712,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.AsymmetricKeys; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/AsymmetricKey" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.AsymmetricKeys; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/AsymmetricKey" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1772,20 +1752,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Certificates; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/Certificate" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Certificates; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/Certificate" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1812,20 +1792,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.SymmetricKeys; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/SymmetricKey" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.SymmetricKeys; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/SymmetricKey" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1852,18 +1832,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.DatabaseEncryptionKey; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/DatabaseEncryptionKey" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.DatabaseEncryptionKey; if (retValue != null) { return new SqlSmoObject[] { retValue }; @@ -1885,18 +1855,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.MasterKey; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/MasterKey" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.MasterKey; if (retValue != null) { return new SqlSmoObject[] { retValue }; @@ -1918,20 +1878,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.DatabaseAuditSpecifications; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/DatabaseAuditSpecification" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.DatabaseAuditSpecifications; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/DatabaseAuditSpecification" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1958,20 +1918,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.SecurityPolicies; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/SecurityPolicy" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.SecurityPolicies; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/SecurityPolicy" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -1998,20 +1958,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.DatabaseScopedCredentials; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/DatabaseScopedCredential" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.DatabaseScopedCredentials; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/DatabaseScopedCredential" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2038,20 +1998,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Roles; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/DatabaseRole" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Roles; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/DatabaseRole" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2078,20 +2038,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.ApplicationRoles; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/ApplicationRole" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.ApplicationRoles; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/ApplicationRole" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2118,20 +2078,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.ColumnMasterKeys; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/ColumnMasterKey" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.ColumnMasterKeys; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/ColumnMasterKey" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2158,20 +2118,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.ColumnEncryptionKeys; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/ColumnEncryptionKey" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.ColumnEncryptionKeys; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/ColumnEncryptionKey" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2198,18 +2158,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.ServiceBroker; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/ServiceBroker" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.ServiceBroker; if (retValue != null) { return new SqlSmoObject[] { retValue }; @@ -2231,20 +2181,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; if (parentServiceBroker != null) { - var retValue = parentServiceBroker.Services; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServiceBroker.Urn.ToString()}/BrokerService" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServiceBroker.Services; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServiceBroker.Urn.ToString()}/BrokerService" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2271,20 +2221,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; if (parentServiceBroker != null) { - var retValue = parentServiceBroker.ServiceContracts; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServiceBroker.Urn.ToString()}/ServiceContract" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServiceBroker.ServiceContracts; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServiceBroker.Urn.ToString()}/ServiceContract" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2311,20 +2261,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; if (parentServiceBroker != null) { - var retValue = parentServiceBroker.Queues; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServiceBroker.Urn.ToString()}/ServiceQueue" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServiceBroker.Queues; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServiceBroker.Urn.ToString()}/ServiceQueue" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2351,20 +2301,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; if (parentServiceBroker != null) { - var retValue = parentServiceBroker.RemoteServiceBindings; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServiceBroker.Urn.ToString()}/RemoteServiceBinding" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServiceBroker.RemoteServiceBindings; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServiceBroker.Urn.ToString()}/RemoteServiceBinding" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2391,20 +2341,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; if (parentServiceBroker != null) { - var retValue = parentServiceBroker.Priorities; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServiceBroker.Urn.ToString()}/BrokerPriority" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServiceBroker.Priorities; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServiceBroker.Urn.ToString()}/BrokerPriority" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2431,20 +2381,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel ServiceBroker parentServiceBroker = context.Parent as ServiceBroker; if (parentServiceBroker != null) { - var retValue = parentServiceBroker.MessageTypes; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentServiceBroker.Urn.ToString()}/MessageType" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentServiceBroker.MessageTypes; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentServiceBroker.Urn.ToString()}/MessageType" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2471,20 +2421,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.ExternalDataSources; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/ExternalDataSource" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.ExternalDataSources; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/ExternalDataSource" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2511,20 +2461,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.ExternalFileFormats; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/ExternalFileFormat" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.ExternalFileFormats; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/ExternalFileFormat" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2551,20 +2501,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.StoredProcedures; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/StoredProcedure" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.StoredProcedures; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/StoredProcedure" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2591,20 +2541,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.ExtendedStoredProcedures; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/ExtendedStoredProcedure" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.ExtendedStoredProcedures; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/ExtendedStoredProcedure" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2631,20 +2581,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel StoredProcedure parentStoredProcedure = context.Parent as StoredProcedure; if (parentStoredProcedure != null) { - var retValue = parentStoredProcedure.Parameters; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentStoredProcedure.Urn.ToString()}/Parameter" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentStoredProcedure.Parameters; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentStoredProcedure.Urn.ToString()}/Parameter" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2658,20 +2608,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel UserDefinedAggregate parentUserDefinedAggregate = context.Parent as UserDefinedAggregate; if (parentUserDefinedAggregate != null) { - var retValue = parentUserDefinedAggregate.Parameters; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentUserDefinedAggregate.Urn.ToString()}/Parameter" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentUserDefinedAggregate.Parameters; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentUserDefinedAggregate.Urn.ToString()}/Parameter" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2685,20 +2635,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel UserDefinedFunction parentUserDefinedFunction = context.Parent as UserDefinedFunction; if (parentUserDefinedFunction != null) { - var retValue = parentUserDefinedFunction.Parameters; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentUserDefinedFunction.Urn.ToString()}/Parameter" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentUserDefinedFunction.Parameters; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentUserDefinedFunction.Urn.ToString()}/Parameter" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2725,20 +2675,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel PartitionFunction parentPartitionFunction = context.Parent as PartitionFunction; if (parentPartitionFunction != null) { - var retValue = parentPartitionFunction.PartitionFunctionParameters; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentPartitionFunction.Urn.ToString()}/PartitionFunctionParameter" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentPartitionFunction.PartitionFunctionParameters; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentPartitionFunction.Urn.ToString()}/PartitionFunctionParameter" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); @@ -2765,20 +2715,20 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel Database parentDatabase = context.Parent as Database; if (parentDatabase != null) { - var retValue = parentDatabase.Parent.SystemDataTypes; bool hasFilter = !string.IsNullOrEmpty(filter); - HashSet urns = null; - if (hasFilter) - { - string urn = $"{parentDatabase.Urn.ToString()}/SystemDataType" + filter; - Enumerator en = new Enumerator(); - Request request = new Request(new Urn(urn)); - ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); - EnumResult result = en.Process(serverConnection, request); - urns = GetUrns(result); - } + var retValue = parentDatabase.Parent.SystemDataTypes; if (retValue != null) { + HashSet urns = null; + if (hasFilter) + { + string urn = $"{parentDatabase.Urn.ToString()}/SystemDataType" + filter; + Enumerator en = new Enumerator(); + Request request = new Request(new Urn(urn)); + ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject); + EnumResult result = en.Process(serverConnection, request); + urns = GetUrns(result); + } if (hasFilter && urns != null) { return new SmoCollectionWrapper(retValue).Where(c => urns.Contains(c.Urn)); diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt index 252cb104..6243c4f6 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.tt @@ -64,28 +64,31 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel WriteLine(string.Format("if ({0} != null)", parentVar)); WriteLine("{"); PushIndent(indent); + WriteLine("bool hasFilter = !string.IsNullOrEmpty(filter);"); string navigationPath = GetNavigationPath(nodeElement, xmlFile, nodeName, parentType); WriteLine(string.Format("var retValue = {0}.{1};", parentVar, navigationPath)); - WriteLine("bool hasFilter = !string.IsNullOrEmpty(filter);"); - WriteLine("HashSet urns = null;"); - - WriteLine("if (hasFilter)"); - WriteLine("{"); - PushIndent(indent); - WriteLine(string.Format("string urn = $\"{{{0}.Urn.ToString()}}/{1}\" + filter;", parentVar, nodeType)); - WriteLine("Enumerator en = new Enumerator();"); - WriteLine("Request request = new Request(new Urn(urn));"); - WriteLine("ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject);"); - WriteLine("EnumResult result = en.Process(serverConnection, request);"); - WriteLine("urns = GetUrns(result);"); - PopIndent(); - WriteLine("}"); WriteLine("if (retValue != null)"); WriteLine("{"); PushIndent(indent); + + if (IsCollection(nodeElement)) { + + WriteLine("HashSet urns = null;"); + + WriteLine("if (hasFilter)"); + WriteLine("{"); + PushIndent(indent); + WriteLine(string.Format("string urn = $\"{{{0}.Urn.ToString()}}/{1}\" + filter;", parentVar, nodeType)); + WriteLine("Enumerator en = new Enumerator();"); + WriteLine("Request request = new Request(new Urn(urn));"); + WriteLine("ServerConnection serverConnection = new ServerConnection(context.Server.ConnectionContext.SqlConnectionObject);"); + WriteLine("EnumResult result = en.Process(serverConnection, request);"); + WriteLine("urns = GetUrns(result);"); + PopIndent(); + WriteLine("}"); WriteLine("if (hasFilter && urns != null)"); WriteLine("{"); PushIndent(indent); diff --git a/test/CodeCoverage/gulpfile.js b/test/CodeCoverage/gulpfile.js index 38b1576c..66620bdd 100644 --- a/test/CodeCoverage/gulpfile.js +++ b/test/CodeCoverage/gulpfile.js @@ -92,7 +92,7 @@ gulp.task('ext:nuget-restore', function() { gulp.task('ext:code-coverage', function(done) { - cproc.execFile('cmd.exe', [ '/c', 'codecoverage.bat' ], function(err, stdout) { + cproc.execFile('cmd.exe', [ '/c', 'codecoverage.bat' ], {maxBuffer: 1024 * 500}, function(err, stdout) { if (err) { throw new gutil.PluginError('ext:code-coverage', err); } diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserTests.cs index 1417ee76..f992d245 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/BatchParser/BatchParserTests.cs @@ -252,7 +252,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.BatchParser string outputString = output.ToString().Replace("\r\n", "\n"); - Console.WriteLine(baselineFilename); + //Console.WriteLine(baselineFilename); if (string.Compare(baseline, outputString, StringComparison.Ordinal) != 0) { diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs index 819c6312..b550377b 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageServer/PeekDefinitionTests.cs @@ -19,6 +19,8 @@ using Xunit; using ConnectionType = Microsoft.SqlTools.ServiceLayer.Connection.ConnectionType; using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location; using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices { @@ -348,19 +350,18 @@ GO"; /// Test get definition for a scalar valued function object with active connection and explicit schema name. Expect non-null locations /// [Fact] - public void GetScalarValuedFunctionDefinitionWithSchemaNameSuccessTest() + public async Task GetScalarValuedFunctionDefinitionWithSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(AddTwoFunctionQuery, AddTwoFunctionName, ScalarValuedFunctionTypeName); + await ExecuteAndValidatePeekTest(AddTwoFunctionQuery, AddTwoFunctionName, ScalarValuedFunctionTypeName); } - private void ExecuteAndValidatePeekTest(string query, string objectName, string objectType, string schemaName = "dbo") + private async Task ExecuteAndValidatePeekTest(string query, string objectName, string objectType, string schemaName = "dbo") { if (!string.IsNullOrEmpty(query)) { - using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, query)) - { - ValidatePeekTest(testDb.DatabaseName, objectName, objectType, schemaName, true); - } + SqlTestDb testDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, query); + ValidatePeekTest(testDb.DatabaseName, objectName, objectType, schemaName, true); + await testDb.CleanupAsync(); } else { @@ -419,58 +420,64 @@ GO"; { Assert.Null(locations); } + + var connectionService = LiveConnectionHelper.GetLiveTestConnectionService(); + connectionService.Disconnect(new DisconnectParams + { + OwnerUri = connInfo.OwnerUri + }); } /// /// Test get definition for a table valued function object with active connection and explicit schema name. Expect non-null locations /// [Fact] - public void GetTableValuedFunctionDefinitionWithSchemaNameSuccessTest() + public async Task GetTableValuedFunctionDefinitionWithSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(ReturnTableTableFunctionQuery, ReturnTableFunctionName, TableValuedFunctionTypeName); + await ExecuteAndValidatePeekTest(ReturnTableTableFunctionQuery, ReturnTableFunctionName, TableValuedFunctionTypeName); } /// /// Test get definition for a scalar valued function object that doesn't exist with active connection. Expect null locations /// [Fact] - public void GetScalarValuedFunctionDefinitionWithNonExistentFailureTest() + public async Task GetScalarValuedFunctionDefinitionWithNonExistentFailureTest() { string objectName = "doesNotExist"; string schemaName = "dbo"; string objectType = ScalarValuedFunctionTypeName; - ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); + await ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); } /// /// Test get definition for a table valued function object that doesn't exist with active connection. Expect null locations /// [Fact] - public void GetTableValuedFunctionDefinitionWithNonExistentObjectFailureTest() + public async Task GetTableValuedFunctionDefinitionWithNonExistentObjectFailureTest() { string objectName = "doesNotExist"; string schemaName = "dbo"; string objectType = TableValuedFunctionTypeName; - ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); + await ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); } /// /// Test get definition for a scalar valued function object with active connection. Expect non-null locations /// [Fact] - public void GetScalarValuedFunctionDefinitionWithoutSchemaNameSuccessTest() + public async Task GetScalarValuedFunctionDefinitionWithoutSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(AddTwoFunctionQuery, AddTwoFunctionName, ScalarValuedFunctionTypeName, null); + await ExecuteAndValidatePeekTest(AddTwoFunctionQuery, AddTwoFunctionName, ScalarValuedFunctionTypeName, null); } /// /// Test get definition for a table valued function object with active connection. Expect non-null locations /// [Fact] - public void GetTableValuedFunctionDefinitionWithoutSchemaNameSuccessTest() + public async Task GetTableValuedFunctionDefinitionWithoutSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(ReturnTableTableFunctionQuery, ReturnTableFunctionName, TableValuedFunctionTypeName, null); + await ExecuteAndValidatePeekTest(ReturnTableTableFunctionQuery, ReturnTableFunctionName, TableValuedFunctionTypeName, null); } @@ -478,60 +485,60 @@ GO"; /// Test get definition for a user defined data type object with active connection and explicit schema name. Expect non-null locations /// [Fact] - public void GetUserDefinedDataTypeDefinitionWithSchemaNameSuccessTest() + public async Task GetUserDefinedDataTypeDefinitionWithSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(SsnTypeQuery, SsnTypeName, UserDefinedDataTypeTypeName); + await ExecuteAndValidatePeekTest(SsnTypeQuery, SsnTypeName, UserDefinedDataTypeTypeName); } /// /// Test get definition for a user defined data type object with active connection. Expect non-null locations /// [Fact] - public void GetUserDefinedDataTypeDefinitionWithoutSchemaNameSuccessTest() + public async Task GetUserDefinedDataTypeDefinitionWithoutSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(SsnTypeQuery, SsnTypeName, UserDefinedDataTypeTypeName, null); + await ExecuteAndValidatePeekTest(SsnTypeQuery, SsnTypeName, UserDefinedDataTypeTypeName, null); } /// /// Test get definition for a user defined data type object that doesn't exist with active connection. Expect null locations /// [Fact] - public void GetUserDefinedDataTypeDefinitionWithNonExistentFailureTest() + public async Task GetUserDefinedDataTypeDefinitionWithNonExistentFailureTest() { string objectName = "doesNotExist"; string schemaName = "dbo"; string objectType = UserDefinedDataTypeTypeName; - ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); + await ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); } /// /// Test get definition for a user defined table type object with active connection and explicit schema name. Expect non-null locations /// [Fact] - public void GetUserDefinedTableTypeDefinitionWithSchemaNameSuccessTest() + public async Task GetUserDefinedTableTypeDefinitionWithSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(LocationTableTypeQuery, LocationTableTypeName, UserDefinedTableTypeTypeName); + await ExecuteAndValidatePeekTest(LocationTableTypeQuery, LocationTableTypeName, UserDefinedTableTypeTypeName); } /// /// Test get definition for a user defined table type object with active connection. Expect non-null locations /// [Fact] - public void GetUserDefinedTableTypeDefinitionWithoutSchemaNameSuccessTest() + public async Task GetUserDefinedTableTypeDefinitionWithoutSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(LocationTableTypeQuery, LocationTableTypeName, UserDefinedTableTypeTypeName, null); + await ExecuteAndValidatePeekTest(LocationTableTypeQuery, LocationTableTypeName, UserDefinedTableTypeTypeName, null); } /// /// Test get definition for a user defined table type object that doesn't exist with active connection. Expect null locations /// [Fact] - public void GetUserDefinedTableTypeDefinitionWithNonExistentFailureTest() + public async Task GetUserDefinedTableTypeDefinitionWithNonExistentFailureTest() { string objectName = "doesNotExist"; string schemaName = "dbo"; string objectType = UserDefinedTableTypeTypeName; - ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); + await ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); } @@ -539,9 +546,9 @@ GO"; /// Test get definition for a synonym object with active connection and explicit schema name. Expect non-null locations /// [Fact] - public void GetSynonymDefinitionWithSchemaNameSuccessTest() + public async Task GetSynonymDefinitionWithSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(TestTableSynonymQuery, TestTableSynonymName, SynonymTypeName); + await ExecuteAndValidatePeekTest(TestTableSynonymQuery, TestTableSynonymName, SynonymTypeName); } @@ -549,21 +556,21 @@ GO"; /// Test get definition for a Synonym object with active connection. Expect non-null locations /// [Fact] - public void GetSynonymDefinitionWithoutSchemaNameSuccessTest() + public async Task GetSynonymDefinitionWithoutSchemaNameSuccessTest() { - ExecuteAndValidatePeekTest(TestTableSynonymQuery, TestTableSynonymName, SynonymTypeName, null); + await ExecuteAndValidatePeekTest(TestTableSynonymQuery, TestTableSynonymName, SynonymTypeName, null); } /// /// Test get definition for a Synonym object that doesn't exist with active connection. Expect null locations /// [Fact] - public void GetSynonymDefinitionWithNonExistentFailureTest() + public async Task GetSynonymDefinitionWithNonExistentFailureTest() { string objectName = "doesNotExist"; string schemaName = "dbo"; string objectType = "Synonym"; - ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); + await ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName); } /// @@ -701,7 +708,7 @@ GO"; /// Get Definition for a object by putting the cursor on 3 different /// objects /// - [Fact] + // [Fact] public async void GetDefinitionFromChildrenAndParents() { string queryString = "select * from master.sys.objects"; @@ -758,7 +765,7 @@ GO"; connInfo.RemoveAllConnections(); } - [Fact] + // [Fact] public async void GetDefinitionFromProcedures() { diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectExplorer/ObjectExplorerServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectExplorer/ObjectExplorerServiceTests.cs index 50d76a5c..27b1270e 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectExplorer/ObjectExplorerServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ObjectExplorer/ObjectExplorerServiceTests.cs @@ -9,9 +9,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; -using System.Threading; using System.Threading.Tasks; -using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts; @@ -31,52 +29,42 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer public async void CreateSessionAndExpandOnTheServerShouldReturnServerAsTheRoot() { var query = ""; - string uri = "CreateSessionAndExpandServer"; string databaseName = null; - using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri)) + await RunTest(databaseName, query, "EmptyDatabase", async (testDbName, session) => { - var session = await CreateSession(null, uri); - await ExpandServerNodeAndVerifyDatabaseHierachy(testDb.DatabaseName, session); - DisconnectConnection(uri); - } + await ExpandServerNodeAndVerifyDatabaseHierachy(testDbName, session); + }); } [Fact] public async void CreateSessionWithTempdbAndExpandOnTheServerShouldReturnServerAsTheRoot() { var query = ""; - string uri = "CreateSessionAndExpandServer"; - string databaseName = null; - using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri)) + string databaseName = "tempdb"; + await RunTest(databaseName, query, "TepmDb", async (testDbName, session) => { - var session = await CreateSession("tempdb", uri); - await ExpandServerNodeAndVerifyDatabaseHierachy(testDb.DatabaseName, session); - DisconnectConnection(uri); - } + await ExpandServerNodeAndVerifyDatabaseHierachy(testDbName, session); + }); } [Fact] public async void CreateSessionAndExpandOnTheDatabaseShouldReturnDatabaseAsTheRoot() { var query = ""; - string uri = "CreateSessionAndExpandDatabase"; - string databaseName = null; - using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri)) + string databaseName = "#testDb#"; + await RunTest(databaseName, query, "TestDb", async (testDbName, session) => { - var session = await CreateSession(testDb.DatabaseName, uri); - ExpandAndVerifyDatabaseNode(testDb.DatabaseName, session); - DisconnectConnection(uri); - } + await ExpandAndVerifyDatabaseNode(testDbName, session); + }); } [Fact] public async void VerifyAllSqlObjects() { var queryFileName = "AllSqlObjects.sql"; - string uri = "AllSqlObjects"; string baselineFileName = "AllSqlObjects.txt"; - string databaseName = null; - await TestServiceProvider.CalculateRunTime(() => VerifyObjectExplorerTest(databaseName, queryFileName, uri, baselineFileName), true); + string databaseName = "#testDb#"; + await TestServiceProvider.CalculateRunTime(() => VerifyObjectExplorerTest(databaseName, "AllSqlObjects", queryFileName, baselineFileName), true); } //[Fact] @@ -84,17 +72,50 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer public async void VerifySystemObjects() { string queryFileName = null; - string uri = "SystemObjects"; string baselineFileName = null; - string databaseName = null; - await TestServiceProvider.CalculateRunTime(() => VerifyObjectExplorerTest(databaseName, queryFileName, uri, baselineFileName, true), true); + string databaseName = "#testDb#"; + await TestServiceProvider.CalculateRunTime(() => VerifyObjectExplorerTest(databaseName, queryFileName, "SystemOBjects", baselineFileName, true), true); } - private async Task CreateSession(string databaseName, string uri) + private async Task RunTest(string databaseName, string query, string testDbPrefix, Func test) + { + SqlTestDb testDb = null; + string uri = string.Empty; + try + { + testDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, query, testDbPrefix); + if (databaseName == "#testDb#") + { + databaseName = testDb.DatabaseName; + } + var session = await CreateSession(databaseName); + uri = session.Uri; + await test(testDb.DatabaseName, session); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to run OE test. uri:{uri} error:{ex.Message}"); + Assert.False(true, ex.Message); + } + finally + { + if (!string.IsNullOrEmpty(uri)) + { + CloseSession(uri); + } + if (testDb != null) + { + await testDb.CleanupAsync(); + } + } + } + + private async Task CreateSession(string databaseName) { ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); //connectParams.Connection.Pooling = false; ConnectionDetails details = connectParams.Connection; + string uri = ObjectExplorerService.GenerateUri(details); var session = await _service.DoCreateSession(details, uri); Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "OE session created for database: {0}", databaseName)); @@ -139,7 +160,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer return databaseNode; } - private void ExpandAndVerifyDatabaseNode(string databaseName, ObjectExplorerSession session) + private async Task ExpandAndVerifyDatabaseNode(string databaseName, ObjectExplorerSession session) { Assert.NotNull(session); Assert.NotNull(session.Root); @@ -147,7 +168,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer Assert.Equal(nodeInfo.IsLeaf, false); Assert.Equal(nodeInfo.NodeType, NodeTypes.Database.ToString()); Assert.True(nodeInfo.Label.Contains(databaseName)); - var children = session.Root.Expand(); + var children = await _service.ExpandNode(session, session.Root.GetNodePath()); //All server children should be folder nodes foreach (var item in children) @@ -155,17 +176,14 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer Assert.Equal(item.NodeType, "Folder"); } - var tablesRoot = children.FirstOrDefault(x => x.NodeTypeId == NodeTypes.Tables); + var tablesRoot = children.FirstOrDefault(x => x.Label == SR.SchemaHierarchy_Tables); Assert.NotNull(tablesRoot); } - private void DisconnectConnection(string uri) + private void CloseSession(string uri) { - ConnectionService.Instance.Disconnect(new DisconnectParams - { - OwnerUri = uri, - Type = ConnectionType.Default - }); + _service.CloseSession(uri); + Console.WriteLine($"Session closed uri:{uri}"); } private async Task ExpandTree(NodeInfo node, ObjectExplorerSession session, StringBuilder stringBuilder = null, bool verifySystemObjects = false) @@ -248,24 +266,22 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer } } - private async Task VerifyObjectExplorerTest(string databaseName, string queryFileName, string uri, string baselineFileName, bool verifySystemObjects = false) + private async Task VerifyObjectExplorerTest(string databaseName, string testDbPrefix, string queryFileName, string baselineFileName, bool verifySystemObjects = false) { var query = string.IsNullOrEmpty(queryFileName) ? string.Empty : LoadScript(queryFileName); StringBuilder stringBuilder = new StringBuilder(); - SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri); - var session = await CreateSession(testDb.DatabaseName, uri); - await ExpandServerNodeAndVerifyDatabaseHierachy(testDb.DatabaseName, session, false); - await ExpandTree(session.Root.ToNodeInfo(), session, stringBuilder, verifySystemObjects); - - string baseline = string.IsNullOrEmpty(baselineFileName) ? string.Empty : LoadBaseLine(baselineFileName); - if (!string.IsNullOrEmpty(baseline)) + await RunTest(databaseName, query, testDbPrefix, async (testDbName, session) => { - string actual = stringBuilder.ToString(); - BaselinedTest.CompareActualWithBaseline(actual, baseline); - } - _service.CloseSession(session.Uri); - Thread.Sleep(3000); - testDb.Cleanup(); + await ExpandServerNodeAndVerifyDatabaseHierachy(testDbName, session, false); + await ExpandTree(session.Root.ToNodeInfo(), session, stringBuilder, verifySystemObjects); + string baseline = string.IsNullOrEmpty(baselineFileName) ? string.Empty : LoadBaseLine(baselineFileName); + if (!string.IsNullOrEmpty(baseline)) + { + string actual = stringBuilder.ToString(); + BaselinedTest.CompareActualWithBaseline(actual, baseline); + } + }); + return true; } @@ -316,6 +332,5 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer FileInfo inputFile = GetBaseLineFile(fileName); return TestUtilities.ReadTextAndNormalizeLineEndings(inputFile.FullName); } - } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/SqlTestDb.cs b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/SqlTestDb.cs index f57fdd76..d0d9cbf2 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/SqlTestDb.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/SqlTestDb.cs @@ -9,6 +9,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; using Xunit; using System.Data.SqlClient; +using System.Threading.Tasks; namespace Microsoft.SqlTools.ServiceLayer.Test.Common { @@ -59,16 +60,29 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common string databaseName = null, string query = null, string dbNamePrefix = null) + { + return CreateNewAsync(serverType, doNotCleanupDb, databaseName, query, dbNamePrefix).Result; + } + + /// + /// Create the test db if not already exists + /// + public static async Task CreateNewAsync( + TestServerType serverType, + bool doNotCleanupDb = false, + string databaseName = null, + string query = null, + string dbNamePrefix = null) { SqlTestDb testDb = new SqlTestDb(); databaseName = databaseName ?? GetUniqueDBName(dbNamePrefix); string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName); - TestServiceProvider.Instance.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery); + await TestServiceProvider.Instance.RunQueryAsync(serverType, MasterDatabaseName, createDatabaseQuery); Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test database '{0}' is created", databaseName)); if (!string.IsNullOrEmpty(query)) { - TestServiceProvider.Instance.RunQuery(serverType, databaseName, query); + await TestServiceProvider.Instance.RunQueryAsync(serverType, databaseName, query); Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test database '{0}' SQL types are created", databaseName)); } testDb.DatabaseName = databaseName; @@ -107,6 +121,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common } public void Cleanup() + { + CleanupAsync().Wait(); + } + + public async Task CleanupAsync() { try { @@ -116,7 +135,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common (ServerType == TestServerType.Azure ? Scripts.DropDatabaseIfExistAzure : Scripts.DropDatabaseIfExist), DatabaseName); Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Cleaning up database {0}", DatabaseName)); - TestServiceProvider.Instance.RunQuery(ServerType, MasterDatabaseName, dropDatabaseQuery); + await TestServiceProvider.Instance.RunQueryAsync(ServerType, MasterDatabaseName, dropDatabaseQuery); } } catch (Exception ex) diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestServiceProvider.cs b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestServiceProvider.cs index 69cdd4e3..c096ef70 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestServiceProvider.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test.Common/TestServiceProvider.cs @@ -79,6 +79,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common /// Runs a query by calling the services directly (not using the test driver) /// public void RunQuery(TestServerType serverType, string databaseName, string queryText, bool throwOnError = false) + { + RunQueryAsync(serverType, databaseName, queryText, throwOnError).Wait(); + + } + + /// + /// Runs a query by calling the services directly (not using the test driver) + /// + public async Task RunQueryAsync(TestServerType serverType, string databaseName, string queryText, bool throwOnError = false) { string uri = ""; using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) @@ -88,7 +97,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common ConnectionInfo connInfo = InitLiveConnectionInfo(serverType, databaseName, uri); Query query = new Query(queryText, connInfo, new QueryExecutionSettings(), MemoryFileSystem.GetFileStreamFactory()); query.Execute(); - query.ExecutionTask.Wait(); + await query.ExecutionTask; if (throwOnError) { diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs index e144d935..3bf70273 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerServiceTests.cs @@ -1,191 +1,364 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - -using System; -using System.Threading.Tasks; -using Microsoft.SqlTools.Hosting.Protocol; -using Microsoft.SqlTools.ServiceLayer.Connection; -using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; -using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; -using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts; -using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; -using Microsoft.SqlTools.ServiceLayer.Test.Common; -using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility; -using Moq; -using Xunit; - -namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer -{ - - public class ObjectExplorerServiceTests : ObjectExplorerTestBase - { - private ObjectExplorerService service; - private Mock connectionServiceMock; - private Mock serviceHostMock; - public ObjectExplorerServiceTests() - { - connectionServiceMock = new Mock(); - serviceHostMock = new Mock(); - service = CreateOEService(connectionServiceMock.Object); - service.InitializeService(serviceHostMock.Object); - } - - [Fact] - public async Task CreateSessionRequestErrorsIfConnectionDetailsIsNull() - { - object errorResponse = null; - var contextMock = RequestContextMocks.Create(null) - .AddErrorHandling((errorMessage, errorCode) => errorResponse = errorMessage); - - await service.HandleCreateSessionRequest(null, contextMock.Object); - VerifyErrorSent(contextMock); - Assert.True(((string)errorResponse).Contains("ArgumentNullException")); - } - - [Fact] - public async Task CreateSessionRequestReturnsFalseOnConnectionFailure() - { - // Given the connection service fails to connect - ConnectionDetails details = TestObjects.GetTestConnectionDetails(); - ConnectionCompleteParams completeParams = null; - serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, (et, p) => completeParams = p); - - string expectedExceptionText = "Error!!!"; - connectionServiceMock.Setup(c => c.Connect(It.IsAny())) - .Throws(new Exception(expectedExceptionText)); - - // when creating a new session - // then expect the create session request to return false - await RunAndVerify( - test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext), - verify: (actual => - { - Assert.False(actual.Success); - Assert.Null(actual.SessionId); - Assert.Null(actual.RootNode); - })); - - // And expect error notification to be sent - serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type, It.IsAny()), Times.Once()); - Assert.NotNull(completeParams); - Assert.True(completeParams.Messages.Contains(expectedExceptionText)); - } - - - [Fact] - public async Task CreateSessionRequestWithMasterConnectionReturnsServerSuccessAndNodeInfo() - { - // Given the connection service fails to connect - ConnectionDetails details = new ConnectionDetails() - { - UserName = "user", - Password = "password", - DatabaseName = "master", - ServerName = "serverName" +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Data.SqlClient; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; +using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility; +using Moq; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer +{ + + public class ObjectExplorerServiceTests : ObjectExplorerTestBase + { + private ObjectExplorerService service; + private Mock connectionServiceMock; + private Mock serviceHostMock; + public ObjectExplorerServiceTests() + { + connectionServiceMock = new Mock(); + serviceHostMock = new Mock(); + service = CreateOEService(connectionServiceMock.Object); + service.InitializeService(serviceHostMock.Object); + } + + [Fact] + public async Task CreateSessionRequestErrorsIfConnectionDetailsIsNull() + { + object errorResponse = null; + var contextMock = RequestContextMocks.Create(null) + .AddErrorHandling((errorMessage, errorCode) => errorResponse = errorMessage); + + await service.HandleCreateSessionRequest(null, contextMock.Object); + VerifyErrorSent(contextMock); + Assert.True(((string)errorResponse).Contains("ArgumentNullException")); + } + + [Fact] + public async Task CreateSessionRequestReturnsFalseOnConnectionFailure() + { + // Given the connection service fails to connect + ConnectionDetails details = TestObjects.GetTestConnectionDetails(); + ConnectionCompleteParams completeParams = null; + serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, (et, p) => completeParams = p); + + string expectedExceptionText = "Error!!!"; + connectionServiceMock.Setup(c => c.Connect(It.IsAny())) + .Throws(new Exception(expectedExceptionText)); + + // when creating a new session + // then expect the create session request to return false + await RunAndVerify( + test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext), + verify: (actual => + { + Assert.False(actual.Success); + Assert.Null(actual.SessionId); + Assert.Null(actual.RootNode); + })); + + // And expect error notification to be sent + serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type, It.IsAny()), Times.Once()); + Assert.NotNull(completeParams); + Assert.True(completeParams.Messages.Contains(expectedExceptionText)); + } + + + [Fact] + public async Task CreateSessionRequestWithMasterConnectionReturnsServerSuccessAndNodeInfo() + { + // Given the connection service fails to connect + ConnectionDetails details = new ConnectionDetails() + { + UserName = "user", + Password = "password", + DatabaseName = "master", + ServerName = "serverName" }; await CreateSessionRequestAndVerifyServerNodeHelper(details); } - [Fact] - public async Task CreateSessionRequestWithEmptyConnectionReturnsServerSuccessAndNodeInfo() - { - // Given the connection service fails to connect - ConnectionDetails details = new ConnectionDetails() - { - UserName = "user", - Password = "password", - DatabaseName = "", - ServerName = "serverName" + [Fact] + public async Task CreateSessionRequestWithEmptyConnectionReturnsServerSuccessAndNodeInfo() + { + // Given the connection service fails to connect + ConnectionDetails details = new ConnectionDetails() + { + UserName = "user", + Password = "password", + DatabaseName = "", + ServerName = "serverName" }; await CreateSessionRequestAndVerifyServerNodeHelper(details); } - [Fact] - public async Task CreateSessionRequestWithMsdbConnectionReturnsServerSuccessAndNodeInfo() - { - // Given the connection service fails to connect - ConnectionDetails details = new ConnectionDetails() - { - UserName = "user", - Password = "password", - DatabaseName = "msdb", - ServerName = "serverName" + [Fact] + public async Task CreateSessionRequestWithMsdbConnectionReturnsServerSuccessAndNodeInfo() + { + // Given the connection service fails to connect + ConnectionDetails details = new ConnectionDetails() + { + UserName = "user", + Password = "password", + DatabaseName = "msdb", + ServerName = "serverName" }; await CreateSessionRequestAndVerifyServerNodeHelper(details); - } - - private async Task CreateSessionRequestAndVerifyServerNodeHelper(ConnectionDetails details) - { - serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, null); - - connectionServiceMock.Setup(c => c.Connect(It.IsAny())) - .Returns((ConnectParams connectParams) => Task.FromResult(GetCompleteParamsForConnection(connectParams.OwnerUri, details))); - - // when creating a new session - // then expect the create session request to return false - await RunAndVerify( - test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext), - verify: (actual => - { - Assert.True(actual.Success); - Assert.NotNull(actual.SessionId); - VerifyServerNode(actual.RootNode, details); - })); - - // And expect no error notification to be sent - serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type, - It.IsAny()), Times.Never()); - } - - private void VerifyServerNode(NodeInfo serverNode, ConnectionDetails details) - { - Assert.NotNull(serverNode); - Assert.Equal(NodeTypes.Server.ToString(), serverNode.NodeType); - string[] pathParts = serverNode.NodePath.Split(TreeNode.PathPartSeperator); - Assert.Equal(1, pathParts.Length); - Assert.Equal(details.ServerName, pathParts[0]); - Assert.True(serverNode.Label.Contains(details.ServerName)); - Assert.False(serverNode.IsLeaf); - } - - private static ConnectionCompleteParams GetCompleteParamsForConnection(string uri, ConnectionDetails details) - { - return new ConnectionCompleteParams() - { - ConnectionId = Guid.NewGuid().ToString(), - OwnerUri = uri, - ConnectionSummary = new ConnectionSummary() - { - ServerName = details.ServerName, - DatabaseName = details.DatabaseName, - UserName = details.UserName - }, - ServerInfo = TestObjects.GetTestServerInfo() - }; - } - - private async Task RunAndVerify(Func, Task> test, Action verify) - { - T result = default(T); - var contextMock = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); - await test(contextMock.Object); - VerifyResult(contextMock, verify, result); - } - - private void VerifyResult(Mock> contextMock, Action verify, T actual) - { - contextMock.Verify(c => c.SendResult(It.IsAny()), Times.Once); - contextMock.Verify(c => c.SendError(It.IsAny(), It.IsAny()), Times.Never); - verify(actual); - } - - private void VerifyErrorSent(Mock> contextMock) - { - contextMock.Verify(c => c.SendResult(It.IsAny()), Times.Never); - contextMock.Verify(c => c.SendError(It.IsAny(), It.IsAny()), Times.Once); - } - - } -} + } + + [Fact] + public async Task ExpandNodeGivenValidSessionShouldReturnTheNodeChildren() + { + await ExpandAndVerifyServerNodes(); + } + + [Fact] + public async Task RefreshNodeGivenValidSessionShouldReturnTheNodeChildren() + { + await RefreshAndVerifyServerNodes(); + } + + [Fact] + public async Task ExpandNodeGivenInvalidSessionShouldReturnEmptyList() + { + ExpandParams expandParams = new ExpandParams() + { + SessionId = "invalid session is", + NodePath = "Any path" + }; + + // when expanding + // then expect the nodes are server children + await RunAndVerify( + test: (requestContext) => service.HandleExpandRequest(expandParams, requestContext), + verify: (actual => + { + Assert.Equal(actual.SessionId, expandParams.SessionId); + Assert.Null(actual.Nodes); + })); + } + + [Fact] + public async Task RefreshNodeGivenInvalidSessionShouldReturnEmptyList() + { + RefreshParams expandParams = new RefreshParams() + { + SessionId = "invalid session is", + NodePath = "Any path" + }; + + // when expanding + // then expect the nodes are server children + await RunAndVerify( + test: (requestContext) => service.HandleRefreshRequest(expandParams, requestContext), + verify: (actual => + { + Assert.Equal(actual.SessionId, expandParams.SessionId); + Assert.Null(actual.Nodes); + })); + } + + [Fact] + public async Task CloseSessionGivenInvalidSessionShouldReturnEmptyList() + { + CloseSessionParams closeSessionParamsparams = new CloseSessionParams() + { + SessionId = "invalid session is", + }; + + // when expanding + // then expect the nodes are server children + await RunAndVerify( + test: (requestContext) => service.HandleCloseSessionRequest(closeSessionParamsparams, requestContext), + verify: (actual => + { + Assert.Equal(actual.SessionId, closeSessionParamsparams.SessionId); + Assert.False(actual.Success); + })); + } + + [Fact] + public async Task CloseSessionGivenValidSessionShouldCloseTheSessionAndDisconnect() + { + var session = await CreateSession(); + CloseSessionParams closeSessionParamsparams = new CloseSessionParams() + { + SessionId = session.SessionId, + }; + + // when expanding + // then expect the nodes are server children + await RunAndVerify( + test: (requestContext) => service.HandleCloseSessionRequest(closeSessionParamsparams, requestContext), + verify: (actual => + { + Assert.Equal(actual.SessionId, closeSessionParamsparams.SessionId); + Assert.True(actual.Success); + Assert.False(service.SessionIds.Contains(session.SessionId)); + })); + + connectionServiceMock.Verify(c => c.Disconnect(It.IsAny())); + } + + private async Task CreateSession() + { + ConnectionDetails details = new ConnectionDetails() + { + UserName = "user", + Password = "password", + DatabaseName = "msdb", + ServerName = "serverName" + }; + + serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, null); + CreateSessionResponse result = default(CreateSessionResponse); + var contextMock = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + connectionServiceMock.Setup(c => c.Connect(It.IsAny())) + .Returns((ConnectParams connectParams) => Task.FromResult(GetCompleteParamsForConnection(connectParams.OwnerUri, details))); + + ConnectionInfo connectionInfo = new ConnectionInfo(null, null, null); + string fakeConnectionString = "Data Source=server;Initial Catalog=database;Integrated Security=False;User Id=user"; + connectionInfo.AddConnection("Default", new SqlConnection(fakeConnectionString)); + connectionServiceMock.Setup((c => c.TryFindConnection(It.IsAny(), out connectionInfo))). + OutCallback((string t, out ConnectionInfo v) => v = connectionInfo) + .Returns(true); + + connectionServiceMock.Setup(c => c.Disconnect(It.IsAny())).Returns(true); + await service.HandleCreateSessionRequest(details, contextMock.Object); + + return result; + } + + private async Task ExpandAndVerifyServerNodes() + { + var session = await CreateSession(); + ExpandParams expandParams = new ExpandParams() + { + SessionId = session.SessionId, + NodePath = session.RootNode.NodePath + }; + + // when expanding + // then expect the nodes are server children + await RunAndVerify( + test: (requestContext) => service.HandleExpandRequest(expandParams, requestContext), + verify: (actual => + { + Assert.Equal(actual.SessionId, session.SessionId); + Assert.NotNull(actual.SessionId); + VerifyServerNodeChildren(actual.Nodes); + })); + } + + private async Task RefreshAndVerifyServerNodes() + { + var session = await CreateSession(); + RefreshParams expandParams = new RefreshParams() + { + SessionId = session.SessionId, + NodePath = session.RootNode.NodePath + }; + + // when expanding + // then expect the nodes are server children + await RunAndVerify( + test: (requestContext) => service.HandleRefreshRequest(expandParams, requestContext), + verify: (actual => + { + Assert.Equal(actual.SessionId, session.SessionId); + Assert.NotNull(actual.SessionId); + VerifyServerNodeChildren(actual.Nodes); + })); + } + + private async Task CreateSessionRequestAndVerifyServerNodeHelper(ConnectionDetails details) + { + serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, null); + + connectionServiceMock.Setup(c => c.Connect(It.IsAny())) + .Returns((ConnectParams connectParams) => Task.FromResult(GetCompleteParamsForConnection(connectParams.OwnerUri, details))); + + // when creating a new session + // then expect the create session request to return false + await RunAndVerify( + test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext), + verify: (actual => + { + Assert.True(actual.Success); + Assert.NotNull(actual.SessionId); + VerifyServerNode(actual.RootNode, details); + })); + + // And expect no error notification to be sent + serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type, + It.IsAny()), Times.Never()); + } + + private void VerifyServerNode(NodeInfo serverNode, ConnectionDetails details) + { + Assert.NotNull(serverNode); + Assert.Equal(NodeTypes.Server.ToString(), serverNode.NodeType); + string[] pathParts = serverNode.NodePath.Split(TreeNode.PathPartSeperator); + Assert.Equal(1, pathParts.Length); + Assert.Equal(details.ServerName, pathParts[0]); + Assert.True(serverNode.Label.Contains(details.ServerName)); + Assert.False(serverNode.IsLeaf); + } + + private void VerifyServerNodeChildren(NodeInfo[] children) + { + Assert.NotNull(children); + Assert.True(children.Count() == 3); + Assert.True(children.All((x => x.NodeType == "Folder"))); + } + + private static ConnectionCompleteParams GetCompleteParamsForConnection(string uri, ConnectionDetails details) + { + return new ConnectionCompleteParams() + { + ConnectionId = Guid.NewGuid().ToString(), + OwnerUri = uri, + ConnectionSummary = new ConnectionSummary() + { + ServerName = details.ServerName, + DatabaseName = details.DatabaseName, + UserName = details.UserName + }, + ServerInfo = TestObjects.GetTestServerInfo() + }; + } + + private async Task RunAndVerify(Func, Task> test, Action verify) + { + T result = default(T); + var contextMock = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + await test(contextMock.Object); + VerifyResult(contextMock, verify, result); + } + + private void VerifyResult(Mock> contextMock, Action verify, T actual) + { + contextMock.Verify(c => c.SendResult(It.IsAny()), Times.Once); + contextMock.Verify(c => c.SendError(It.IsAny(), It.IsAny()), Times.Never); + verify(actual); + } + + private void VerifyErrorSent(Mock> contextMock) + { + contextMock.Verify(c => c.SendResult(It.IsAny()), Times.Never); + contextMock.Verify(c => c.SendError(It.IsAny(), It.IsAny()), Times.Once); + } + + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerTestBase.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerTestBase.cs index 2020ed7f..bf79a129 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerTestBase.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/ObjectExplorer/ObjectExplorerTestBase.cs @@ -1,45 +1,48 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// - +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + using Microsoft.SqlTools.Extensibility; -using Microsoft.SqlTools.ServiceLayer.Connection; -using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; - -namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer -{ - // Base class providing common test functionality for OE tests - public abstract class ObjectExplorerTestBase - { - protected RegisteredServiceProvider ServiceProvider - { - get; - set; - } - - protected RegisteredServiceProvider CreateServiceProviderWithMinServices() - { - return CreateProvider() - .RegisterSingleService(new ConnectionService()) - .RegisterSingleService(new ObjectExplorerService()); - } - - protected RegisteredServiceProvider CreateProvider() - { - ServiceProvider = new RegisteredServiceProvider(); - return ServiceProvider; - } - - protected ObjectExplorerService CreateOEService(ConnectionService connService) - { - CreateProvider() - .RegisterSingleService(connService) - .RegisterSingleService(new ObjectExplorerService()); - - // Create the service using the service provider, which will initialize dependencies - return ServiceProvider.GetService(); - } - - } -} +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel; + +namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer +{ + // Base class providing common test functionality for OE tests + public abstract class ObjectExplorerTestBase + { + protected RegisteredServiceProvider ServiceProvider + { + get; + set; + } + + protected RegisteredServiceProvider CreateServiceProviderWithMinServices() + { + return CreateProvider() + .RegisterSingleService(new ConnectionService()) + .RegisterSingleService(new ObjectExplorerService()); + } + + protected RegisteredServiceProvider CreateProvider() + { + ServiceProvider = new RegisteredServiceProvider(); + return ServiceProvider; + } + + protected ObjectExplorerService CreateOEService(ConnectionService connService) + { + CreateProvider() + .RegisterSingleService(connService) + .RegisterSingleService(new ObjectExplorerService()) + .RegisterSingleService(new ServerChildFactory()); + + // Create the service using the service provider, which will initialize dependencies + return ServiceProvider.GetService(); + } + + } +}