예제 #1
0
        public void ReliableConnectionHelperTest()
        {
            using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
            {
                var            result     = LiveConnectionHelper.InitLiveConnectionInfo(null, queryTempFile.FilePath);
                ConnectionInfo connInfo   = result.ConnectionInfo;
                DbConnection   connection = connInfo.ConnectionTypeToConnectionMap[ConnectionType.Default];
                connection.Open();

                Assert.True(connection.State == ConnectionState.Open, "Connection should be open.");
                Assert.True(ReliableConnectionHelper.IsAuthenticatingDatabaseMaster(connection));

                SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
                Assert.True(ReliableConnectionHelper.IsAuthenticatingDatabaseMaster(builder, null));
                ReliableConnectionHelper.TryAddAlwaysOnConnectionProperties(builder, new SqlConnectionStringBuilder());

                Assert.NotNull(ReliableConnectionHelper.GetServerName(connection));
                Assert.NotNull(ReliableConnectionHelper.ReadServerVersion(connection));

                Assert.NotNull(ReliableConnectionHelper.GetAsSqlConnection(connection));

                ReliableConnectionHelper.ServerInfo info = ReliableConnectionHelper.GetServerVersion(connection);
                Assert.NotNull(ReliableConnectionHelper.IsVersionGreaterThan2012RTM(info));
            }
        }
예제 #2
0
        public void TestGetServerVersion()
        {
            TestUtils.RunIfWindows(() =>
            {
                using (var connection = CreateTestConnection())
                {
                    Assert.NotNull(connection);
                    connection.Open();

                    ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
                    ReliableConnectionHelper.ServerInfo serverInfo2;
                    using (var connection2 = CreateTestConnection())
                    {
                        connection2.Open();
                        serverInfo2 = ReliableConnectionHelper.GetServerVersion(connection);
                    }

                    Assert.NotNull(serverInfo);
                    Assert.NotNull(serverInfo2);
                    Assert.True(serverInfo.ServerMajorVersion != 0);
                    Assert.True(serverInfo.ServerMajorVersion == serverInfo2.ServerMajorVersion);
                    Assert.True(serverInfo.ServerMinorVersion == serverInfo2.ServerMinorVersion);
                    Assert.True(serverInfo.ServerReleaseVersion == serverInfo2.ServerReleaseVersion);
                    Assert.True(serverInfo.ServerEdition == serverInfo2.ServerEdition);
                    Assert.True(serverInfo.IsCloud == serverInfo2.IsCloud);
                    Assert.True(serverInfo.AzureVersion == serverInfo2.AzureVersion);
                }
            });
        }
예제 #3
0
        public async void InvokeSqlAssessmentServerTest()
        {
            var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo("master");

            var connection = liveConnection.ConnectionInfo.AllConnections.FirstOrDefault();

            Debug.Assert(connection != null, "Live connection is always expected providing a connection");

            var serverInfo = ReliableConnectionHelper.GetServerVersion(connection);

            var response = await CallAssessment <AssessmentResultItem>(
                nameof(SqlAssessmentService.InvokeSqlAssessment),
                SqlObjectType.Server,
                liveConnection);

            Assert.All(
                response.Items,
                i =>
            {
                Assert.NotNull(i.Message);
                Assert.NotEmpty(i.Message);
                Assert.Equal(serverInfo.ServerName, i.TargetName);

                if (i.Kind == 0)
                {
                    AssertInfoPresent(i);
                }
            });
        }
예제 #4
0
        /// <summary>
        /// Creates a ConnectionCompleteParams as a response to a successful connection.
        /// Also sets the DatabaseName and IsAzure properties of ConnectionInfo.
        /// </summary>
        /// <returns>A ConnectionCompleteParams in response to the successful connection</returns>
        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);
        }
        public void ReliableConnectionHelperTest()
        {
            ScriptFile     scriptFile;
            ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfo(out scriptFile);

            Assert.True(ReliableConnectionHelper.IsAuthenticatingDatabaseMaster(connInfo.SqlConnection));

            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

            Assert.True(ReliableConnectionHelper.IsAuthenticatingDatabaseMaster(builder));
            ReliableConnectionHelper.TryAddAlwaysOnConnectionProperties(builder, new SqlConnectionStringBuilder());

            Assert.NotNull(ReliableConnectionHelper.GetServerName(connInfo.SqlConnection));
            Assert.NotNull(ReliableConnectionHelper.ReadServerVersion(connInfo.SqlConnection));

            Assert.NotNull(ReliableConnectionHelper.GetAsSqlConnection(connInfo.SqlConnection));

            ServerInfo info = ReliableConnectionHelper.GetServerVersion(connInfo.SqlConnection);

            Assert.NotNull(ReliableConnectionHelper.IsVersionGreaterThan2012RTM(info));
        }
        public void ReliableConnectionHelperTest()
        {
            var            result     = LiveConnectionHelper.InitLiveConnectionInfo();
            ConnectionInfo connInfo   = result.ConnectionInfo;
            DbConnection   connection = connInfo.ConnectionTypeToConnectionMap[ConnectionType.Default];


            Assert.True(ReliableConnectionHelper.IsAuthenticatingDatabaseMaster(connection));

            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();

            Assert.True(ReliableConnectionHelper.IsAuthenticatingDatabaseMaster(builder));
            ReliableConnectionHelper.TryAddAlwaysOnConnectionProperties(builder, new SqlConnectionStringBuilder());

            Assert.NotNull(ReliableConnectionHelper.GetServerName(connection));
            Assert.NotNull(ReliableConnectionHelper.ReadServerVersion(connection));

            Assert.NotNull(ReliableConnectionHelper.GetAsSqlConnection(connection));

            ReliableConnectionHelper.ServerInfo info = ReliableConnectionHelper.GetServerVersion(connection);
            Assert.NotNull(ReliableConnectionHelper.IsVersionGreaterThan2012RTM(info));
        }
예제 #7
0
        public async void GetAssessmentItemsServerTest()
        {
            var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo("master");

            var connection = liveConnection.ConnectionInfo.AllConnections.FirstOrDefault();

            Debug.Assert(connection != null, "Live connection is always expected providing a connection");

            var serverInfo = ReliableConnectionHelper.GetServerVersion(connection);

            var response = await CallAssessment <CheckInfo>(
                nameof(SqlAssessmentService.GetAssessmentItems),
                SqlObjectType.Server,
                liveConnection);

            Assert.All(
                response.Items,
                i =>
            {
                AssertInfoPresent(i);
                Assert.Equal(serverInfo.ServerName, i.TargetName);
            });
        }
예제 #8
0
        /// <summary>
        /// Open a connection with the specified connection details
        /// </summary>
        /// <param name="connectionParams"></param>
        public async Task <ConnectionCompleteParams> Connect(ConnectParams connectionParams)
        {
            // Validate parameters
            string paramValidationErrorMessage;

            if (connectionParams == null)
            {
                return(new ConnectionCompleteParams
                {
                    Messages = SR.ConnectionServiceConnectErrorNullParams
                });
            }
            if (!connectionParams.IsValid(out paramValidationErrorMessage))
            {
                return(new ConnectionCompleteParams
                {
                    OwnerUri = connectionParams.OwnerUri,
                    Messages = paramValidationErrorMessage
                });
            }

            // Resolve if it is an existing connection
            // Disconnect active connection if the URI is already connected
            ConnectionInfo connectionInfo;

            if (ownerToConnectionMap.TryGetValue(connectionParams.OwnerUri, out connectionInfo))
            {
                var disconnectParams = new DisconnectParams()
                {
                    OwnerUri = connectionParams.OwnerUri
                };
                Disconnect(disconnectParams);
            }
            connectionInfo = new ConnectionInfo(ConnectionFactory, connectionParams.OwnerUri, connectionParams.Connection);

            // try to connect
            var response = new ConnectionCompleteParams {
                OwnerUri = connectionParams.OwnerUri
            };
            CancellationTokenSource source = null;

            try
            {
                // build the connection string from the input parameters
                string connectionString = BuildConnectionString(connectionInfo.ConnectionDetails);

                // create a sql connection instance
                connectionInfo.SqlConnection = connectionInfo.Factory.CreateSqlConnection(connectionString);

                // Add a cancellation token source so that the connection OpenAsync() can be cancelled
                using (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 (ownerToCancellationTokenSourceMap.TryGetValue(connectionParams.OwnerUri, out currentSource))
                        {
                            currentSource.Cancel();
                        }
                        ownerToCancellationTokenSourceMap[connectionParams.OwnerUri] = source;
                    }

                    // Create a task to handle cancellation requests
                    var cancellationTask = Task.Run(() =>
                    {
                        source.Token.WaitHandle.WaitOne();
                        try
                        {
                            source.Token.ThrowIfCancellationRequested();
                        }
                        catch (ObjectDisposedException)
                        {
                            // Ignore
                        }
                    });

                    var openTask = Task.Run(async() => {
                        await connectionInfo.SqlConnection.OpenAsync(source.Token);
                    });

                    // Open the connection
                    await Task.WhenAny(openTask, cancellationTask).Unwrap();

                    source.Cancel();
                }
            }
            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 (ownerToCancellationTokenSourceMap.TryGetValue(connectionParams.OwnerUri, out sourceValue) && sourceValue == source)
                    {
                        ownerToCancellationTokenSourceMap.TryRemove(connectionParams.OwnerUri, out sourceValue);
                    }
                }
            }

            ownerToConnectionMap[connectionParams.OwnerUri] = connectionInfo;

            // 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 = connectionInfo.SqlConnection.Database;
            response.ConnectionSummary = new ConnectionSummary
            {
                ServerName   = connectionInfo.ConnectionDetails.ServerName,
                DatabaseName = connectionInfo.ConnectionDetails.DatabaseName,
                UserName     = connectionInfo.ConnectionDetails.UserName,
            };

            // invoke callback notifications
            InvokeOnConnectionActivities(connectionInfo);

            // try to get information about the connected SQL Server instance
            try
            {
                var          reliableConnection = connectionInfo.SqlConnection as ReliableSqlConnection;
                DbConnection connection         = reliableConnection != null?reliableConnection.GetUnderlyingConnection() : connectionInfo.SqlConnection;

                ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
                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;
            }
            catch (Exception ex)
            {
                response.Messages = ex.ToString();
            }

            // return the connection result
            response.ConnectionId = connectionInfo.ConnectionId.ToString();
            return(response);
        }
예제 #9
0
        /// <summary>
        /// This function obtains a live connection, then calls
        /// an assessment operation specified by <paramref name="assessmentFunc"/>
        /// </summary>
        /// <typeparam name="TResult">
        /// SQL Assessment result item type.
        /// </typeparam>
        /// <param name="requestParams">
        /// Request parameters passed from the host.
        /// </param>
        /// <param name="connectParams">
        /// Connection parameters used to identify and access the target.
        /// </param>
        /// <param name="taskUri">
        /// An URI identifying the request task to enable concurrent execution.
        /// </param>
        /// <param name="assessmentFunc">
        /// A function performing assessment operation for given target.
        /// </param>
        /// <returns>
        /// Returns <see cref="AssessmentResult{TResult}"/> for given target.
        /// </returns>
        internal async Task <AssessmentResult <TResult> > CallAssessmentEngine <TResult>(
            AssessmentParams requestParams,
            ConnectParams connectParams,
            string taskUri,
            Func <SqlObjectLocator, Task <List <TResult> > > assessmentFunc)
            where TResult : AssessmentItemInfo

        {
            var result = new AssessmentResult <TResult>
            {
                ApiVersion = ApiVersion
            };

            await ConnectionService.Connect(connectParams);

            var connection = await ConnectionService.Instance.GetOrOpenConnection(taskUri, ConnectionType.Query);

            try
            {
                var serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
                var hostInfo   = ReliableConnectionHelper.GetServerHostInfo(connection);

                var server = new SqlObjectLocator
                {
                    Connection    = connection,
                    EngineEdition = GetEngineEdition(serverInfo.EngineEditionId),
                    Name          = serverInfo.ServerName,
                    ServerName    = serverInfo.ServerName,
                    Type          = SqlObjectType.Server,
                    Urn           = serverInfo.ServerName,
                    Version       = Version.Parse(serverInfo.ServerVersion),
                    Platform      = hostInfo.Platform
                };

                switch (requestParams.TargetType)
                {
                case SqlObjectType.Server:
                    Logger.Write(
                        TraceEventType.Verbose,
                        $"SQL Assessment: running an operation on a server, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");

                    result.Items.AddRange(await assessmentFunc(server));

                    Logger.Write(
                        TraceEventType.Verbose,
                        $"SQL Assessment: finished an operation on a server, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
                    break;

                case SqlObjectType.Database:
                    var db = GetDatabaseLocator(server, connection.Database);
                    Logger.Write(
                        TraceEventType.Verbose,
                        $"SQL Assessment: running an operation on a database, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");

                    result.Items.AddRange(await assessmentFunc(db));

                    Logger.Write(
                        TraceEventType.Verbose,
                        $"SQL Assessment: finished an operation on a database, platform:{server.Platform}, edition:{server.EngineEdition.ToString()}, version:{server.Version}");
                    break;
                }

                result.Success = true;
            }
            finally
            {
                ActiveRequests.TryRemove(taskUri, out _);
                ConnectionService.Disconnect(new DisconnectParams {
                    OwnerUri = taskUri, Type = null
                });
            }

            return(result);
        }