Add SqlExceptionTranslator for custom SQL error handling
Introduced SqlExceptionTranslator and ISqlExceptionTranslator to translate SQL exceptions into user-friendly error messages for bad request scenarios. Uses configurable options to identify relevant error numbers and format messages with templates.
This commit is contained in:
@@ -0,0 +1,61 @@
|
|||||||
|
using Microsoft.Data.SqlClient;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using ReC.Application.Common.Options;
|
||||||
|
|
||||||
|
namespace ReC.Application.Common.Procedures;
|
||||||
|
|
||||||
|
internal interface ISqlExceptionTranslator
|
||||||
|
{
|
||||||
|
bool IsBadRequestDataIssue(SqlException exception);
|
||||||
|
|
||||||
|
string BuildBadRequestMessage(string operation, string? entity, SqlException exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class SqlExceptionTranslator : ISqlExceptionTranslator
|
||||||
|
{
|
||||||
|
private readonly IOptionsMonitor<SqlExceptionTranslatorOptions> _optionsMonitor;
|
||||||
|
|
||||||
|
public SqlExceptionTranslator(IOptionsMonitor<SqlExceptionTranslatorOptions> optionsMonitor)
|
||||||
|
{
|
||||||
|
_optionsMonitor = optionsMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsBadRequestDataIssue(SqlException exception)
|
||||||
|
{
|
||||||
|
var options = _optionsMonitor.CurrentValue;
|
||||||
|
|
||||||
|
if (options.BadRequestErrorNumbers is { Count: > 0 } &&
|
||||||
|
options.BadRequestErrorNumbers.Contains(exception.Number))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return options.BadRequestMessages?.ContainsKey(exception.Number) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string BuildBadRequestMessage(string operation, string? entity, SqlException exception)
|
||||||
|
{
|
||||||
|
var target = string.IsNullOrWhiteSpace(entity) ? "object" : entity;
|
||||||
|
var options = _optionsMonitor.CurrentValue;
|
||||||
|
var template = ResolveTemplate(options, exception.Number);
|
||||||
|
|
||||||
|
return template
|
||||||
|
.Replace("{Operation}", operation)
|
||||||
|
.Replace("{Target}", target)
|
||||||
|
.Replace("{ErrorMessage}", exception.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ResolveTemplate(SqlExceptionTranslatorOptions options, int errorNumber)
|
||||||
|
{
|
||||||
|
if (options.BadRequestMessages is not null &&
|
||||||
|
options.BadRequestMessages.TryGetValue(errorNumber, out var template) &&
|
||||||
|
!string.IsNullOrWhiteSpace(template))
|
||||||
|
{
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.IsNullOrWhiteSpace(options.DefaultBadRequestMessage)
|
||||||
|
? SqlExceptionTranslatorOptions.DefaultFallbackMessage
|
||||||
|
: options.DefaultBadRequestMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user