- Что такое TDomain : тип объекта домена использовать имя типа при журналировании
- Что такое TRow: это объект, представляющий строку в базе данных
- Что такое TLoggerCategory: думаю, для ILogger это очевидно
using Microsoft.Extensions.Logging;
using Npgsql;
namespace Infrastructure.Persistence.Postgres.Helpers;
internal static class DapperExtensions
{
public static async Task OpenConnection(this PostgresConnectionFactory connectionFactory)
{
var connection = connectionFactory.CreateConnection();
await connection.OpenAsync();
return connection;
}
public static async Task ExecuteAsync(
this NpgsqlConnection connection,
ILogger logger,
string sql,
TRow row,
bool canDoNoEffect = false,
NpgsqlTransaction? transaction = null)
{
var affectedRows = 0;
try
{
affectedRows = await connection.ExecuteAsync(sql, row);
}
catch (PostgresException ex) when (ex.SqlState == "23505")
{
await RollbackTransactionIfnotNullAsync(transaction);
logger.LogError("Constraint Violation: constraint violated for: {Entity}", typeof(TDomain).Name);
throw PersistenceErrors.ConstraintVoilation($"Constraint Violation: constraint violated for {typeof(TDomain).Name}.", ex);
}
catch (NpgsqlException ex)
{
throw HandleNpgsqlException(logger, ex);
}
catch (Exception ex)
{
throw HandleUnexpectedException(logger, ex);
}
if(canDoNoEffect is false)
EnsureRowsWhereAffected(affectedRows, logger);
}
private static Exception HandleNpgsqlException(ILogger logger, Exception ex)
{
var message = "Database connection or protocol error";
logger.LogCritical(ex, message);
return PersistenceErrors.ConnectionError(message, ex);
}
private static Exception HandleUnexpectedException(ILogger logger, Exception ex)
{
var message = "Unexpected database error";
logger.LogCritical(ex, message);
return PersistenceErrors.DatabaseError(message, ex);
}
private static void EnsureRowsWhereAffected(int affectedRows, ILogger logger)
{
if (NoRowsWhereAffected(affectedRows))
{
logger.LogWarning("Failed to insert {RecordType}", typeof(TDomain).Name);
throw PersistenceErrors.InvalidOperation($"Failed to insert {typeof(TDomain).Name}");
}
}
private static bool NoRowsWhereAffected(int affectedRows)
{
return affectedRows == 0;
}
private static async Task RollbackTransactionIfnotNullAsync(NpgsqlTransaction? transaction)
{
if (transaction is not null)
await transaction.RollbackAsync();
}
public static async Task ExecuteAsync(
this NpgsqlConnection connection,
ILogger logger,
string sql,
IEnumerable rows)
{
using var transaction = await connection.BeginTransactionAsync();
foreach (var row in rows)
{
await ExecuteAsync(connection, logger, sql, row, transaction: transaction);
}
transaction.Commit();
}
public static async Task QueryAsync(
this NpgsqlConnection connection,
ILogger logger,
string sql,
Object? param = null)
{
try
{
return await connection.QueryAsync(sql, param);
}
catch (NpgsqlException ex)
{
throw HandleNpgsqlException(logger, ex);
throw;
}
catch (Exception ex)
{
throw HandleUnexpectedException(logger, ex);
throw;
}
}
public static async Task QuerySingleOrDefaultAsync(
this NpgsqlConnection connection,
ILogger logger,
string sql,
Object? param = null)
{
try
{
return await connection.QuerySingleOrDefaultAsync(sql, param);
}
catch (NpgsqlException ex)
{
throw HandleNpgsqlException(logger, ex);
}
catch (Exception ex)
{
throw HandleUnexpectedException(logger, ex);
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... on-methods
Мобильная версия