diff --git a/src/SqlAsyncCollector.cs b/src/SqlAsyncCollector.cs index 221204c09..803587c5e 100644 --- a/src/SqlAsyncCollector.cs +++ b/src/SqlAsyncCollector.cs @@ -95,7 +95,7 @@ public SqlAsyncCollector(IConfiguration configuration, SqlAttribute attribute, I using (SqlConnection connection = BuildConnection(attribute.ConnectionStringSetting, configuration)) { this._logger.LogDebugWithThreadId("BEGIN OpenSqlAsyncCollectorVerifyDatabaseSupportedConnection"); - connection.Open(); + connection.OpenAsyncWithSqlErrorHandling(CancellationToken.None).Wait(); this._logger.LogDebugWithThreadId("END OpenSqlAsyncCollectorVerifyDatabaseSupportedConnection"); VerifyDatabaseSupported(connection, logger, CancellationToken.None).Wait(); } diff --git a/src/SqlBindingUtilities.cs b/src/SqlBindingUtilities.cs index 29547ee88..e561690ff 100644 --- a/src/SqlBindingUtilities.cs +++ b/src/SqlBindingUtilities.cs @@ -203,5 +203,35 @@ public static async Task VerifyDatabaseSupported(SqlConnection connection, ILogg } } } + + /// + /// Opens a connection and handles some specific errors if they occur. + /// + /// The connection to open + /// The cancellation token to pass to the OpenAsync call + /// The task that will be completed when the connection is made + /// Thrown if an error occurred that we want to wrap with more information + internal static async Task OpenAsyncWithSqlErrorHandling(this SqlConnection connection, CancellationToken cancellationToken) + { + try + { + await connection.OpenAsync(cancellationToken); + } + catch (Exception e) + { + SqlException sqlEx = e is AggregateException a ? a.InnerExceptions.OfType().First() : + e is SqlException s ? s : + null; + // Error number for: + // A connection was successfully established with the server, but then an error occurred during the login process. + // The certificate chain was issued by an authority that is not trusted. + // Add on some more information to help the user figure out how to solve it + if (sqlEx?.Number == -2146893019) + { + throw new InvalidOperationException("The default values for encryption on connections have been changed, please review your configuration to ensure you have the correct values for your server. See https://aka.ms/afsqlext-connection for more details.", e); + } + throw; + } + } } } \ No newline at end of file diff --git a/src/SqlConverters.cs b/src/SqlConverters.cs index ddb872a1c..48386632e 100644 --- a/src/SqlConverters.cs +++ b/src/SqlConverters.cs @@ -180,7 +180,7 @@ public virtual async Task BuildItemFromAttributeAsync(SqlAttribute attri { adapter.SelectCommand = command; this._logger.LogDebugWithThreadId("BEGIN OpenBuildItemFromAttributeAsyncConnection"); - await connection.OpenAsync(); + await connection.OpenAsyncWithSqlErrorHandling(CancellationToken.None); this._logger.LogDebugWithThreadId("END OpenBuildItemFromAttributeAsyncConnection"); Dictionary props = connection.AsConnectionProps(); TelemetryInstance.TrackConvert(type, props); diff --git a/src/TriggerBinding/SqlTriggerListener.cs b/src/TriggerBinding/SqlTriggerListener.cs index 27b199d08..7171e6e8a 100644 --- a/src/TriggerBinding/SqlTriggerListener.cs +++ b/src/TriggerBinding/SqlTriggerListener.cs @@ -122,7 +122,7 @@ public async Task StartAsync(CancellationToken cancellationToken) using (var connection = new SqlConnection(this._connectionString)) { this._logger.LogDebugWithThreadId("BEGIN OpenListenerConnection"); - await connection.OpenAsync(cancellationToken); + await connection.OpenAsyncWithSqlErrorHandling(cancellationToken); this._logger.LogDebugWithThreadId("END OpenListenerConnection"); this._telemetryProps.AddConnectionProps(connection);