diff --git a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlAccountRepository.cs b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlAccountRepository.cs index a8c9801..8d998cc 100644 --- a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlAccountRepository.cs +++ b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlAccountRepository.cs @@ -1,4 +1,3 @@ -using System.Data; using Managing.Application.Abstractions.Repositories; using Managing.Application.Abstractions.Services; using Managing.Domain.Accounts; @@ -17,27 +16,7 @@ public class PostgreSqlAccountRepository : IAccountRepository _cacheService = cacheService; } - /// - /// Ensures the database connection is open before executing queries - /// - private async Task EnsureConnectionOpenAsync() - { - if (_context.Database.GetDbConnection().State != ConnectionState.Open) - { - await _context.Database.OpenConnectionAsync(); - } - } - /// - /// Safely closes the database connection if it was opened by us - /// - private async Task SafeCloseConnectionAsync() - { - if (_context.Database.GetDbConnection().State == ConnectionState.Open) - { - await _context.Database.CloseConnectionAsync(); - } - } public void DeleteAccountByName(string name) { @@ -55,7 +34,7 @@ public class PostgreSqlAccountRepository : IAccountRepository { try { - await EnsureConnectionOpenAsync(); + await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); var accountEntity = await _context.Accounts .AsNoTracking() @@ -65,11 +44,10 @@ public class PostgreSqlAccountRepository : IAccountRepository return PostgreSqlMappers.Map(accountEntity); } - catch (Exception) + finally { - // If there's an error, try to reset the connection - await SafeCloseConnectionAsync(); - throw; + // Always ensure the connection is closed after the operation + await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context); } } @@ -108,7 +86,7 @@ public class PostgreSqlAccountRepository : IAccountRepository { try { - await EnsureConnectionOpenAsync(); + await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); // Use proper async operations with AsNoTracking for optimal performance var accountEntities = await _context.Accounts @@ -119,11 +97,10 @@ public class PostgreSqlAccountRepository : IAccountRepository return PostgreSqlMappers.Map(accountEntities); } - catch (Exception) + finally { - // If there's an error, try to reset the connection - await SafeCloseConnectionAsync(); - throw; + // Always ensure the connection is closed after the operation + await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context); } } diff --git a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlBotRepository.cs b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlBotRepository.cs index dbc5a06..86ee99b 100644 --- a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlBotRepository.cs +++ b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlBotRepository.cs @@ -137,14 +137,24 @@ public class PostgreSqlBotRepository : IBotRepository public async Task> GetBotsByIdsAsync(IEnumerable identifiers) { - var entities = await _context.Bots - .AsNoTracking() - .Include(m => m.User) - .Where(b => identifiers.Contains(b.Identifier)) - .ToListAsync() - .ConfigureAwait(false); + try + { + await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); - return PostgreSqlMappers.Map(entities); + var entities = await _context.Bots + .AsNoTracking() + .Include(m => m.User) + .Where(b => identifiers.Contains(b.Identifier)) + .ToListAsync() + .ConfigureAwait(false); + + return PostgreSqlMappers.Map(entities); + } + finally + { + // Always ensure the connection is closed after the operation + await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context); + } } public async Task<(IEnumerable Bots, int TotalCount)> GetBotsPaginatedAsync( diff --git a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlConnectionHelper.cs b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlConnectionHelper.cs new file mode 100644 index 0000000..8124cc2 --- /dev/null +++ b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlConnectionHelper.cs @@ -0,0 +1,34 @@ +using System.Data; +using Microsoft.EntityFrameworkCore; + +namespace Managing.Infrastructure.Databases.PostgreSql; + +/// +/// Helper class for managing PostgreSQL database connections in Entity Framework repositories +/// +public static class PostgreSqlConnectionHelper +{ + /// + /// Ensures the database connection is open before executing queries + /// + /// The DbContext to manage the connection for + public static async Task EnsureConnectionOpenAsync(DbContext context) + { + if (context.Database.GetDbConnection().State != ConnectionState.Open) + { + await context.Database.OpenConnectionAsync(); + } + } + + /// + /// Safely closes the database connection if it was opened by us + /// + /// The DbContext to manage the connection for + public static async Task SafeCloseConnectionAsync(DbContext context) + { + if (context.Database.GetDbConnection().State == ConnectionState.Open) + { + await context.Database.CloseConnectionAsync(); + } + } +} diff --git a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlUserRepository.cs b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlUserRepository.cs index 92811f6..d02808a 100644 --- a/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlUserRepository.cs +++ b/src/Managing.Infrastructure.Database/PostgreSql/PostgreSqlUserRepository.cs @@ -1,4 +1,3 @@ -using System.Data; using Managing.Application.Abstractions.Repositories; using Managing.Domain.Users; using Microsoft.EntityFrameworkCore; @@ -14,33 +13,13 @@ public class PostgreSqlUserRepository : IUserRepository _context = context; } - /// - /// Ensures the database connection is open before executing queries - /// - private async Task EnsureConnectionOpenAsync() - { - if (_context.Database.GetDbConnection().State != ConnectionState.Open) - { - await _context.Database.OpenConnectionAsync(); - } - } - /// - /// Safely closes the database connection if it was opened by us - /// - private async Task SafeCloseConnectionAsync() - { - if (_context.Database.GetDbConnection().State == ConnectionState.Open) - { - await _context.Database.CloseConnectionAsync(); - } - } public async Task GetUserByAgentNameAsync(string agentName) { try { - await EnsureConnectionOpenAsync(); + await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); var userEntity = await _context.Users .AsNoTracking() @@ -49,11 +28,10 @@ public class PostgreSqlUserRepository : IUserRepository return PostgreSqlMappers.Map(userEntity); } - catch (Exception) + finally { - // If there's an error, try to reset the connection - await SafeCloseConnectionAsync(); - throw; + // Always ensure the connection is closed after the operation + await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context); } } @@ -61,7 +39,7 @@ public class PostgreSqlUserRepository : IUserRepository { try { - await EnsureConnectionOpenAsync(); + await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); var userEntity = await _context.Users .AsNoTracking() @@ -70,11 +48,10 @@ public class PostgreSqlUserRepository : IUserRepository return PostgreSqlMappers.Map(userEntity); } - catch (Exception) + finally { - // If there's an error, try to reset the connection - await SafeCloseConnectionAsync(); - throw; + // Always ensure the connection is closed after the operation + await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context); } } @@ -82,7 +59,7 @@ public class PostgreSqlUserRepository : IUserRepository { try { - await EnsureConnectionOpenAsync(); + await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context); var userEntities = await _context.Users .AsNoTracking() @@ -91,11 +68,10 @@ public class PostgreSqlUserRepository : IUserRepository return userEntities.Select(PostgreSqlMappers.Map); } - catch (Exception) + finally { - // If there's an error, try to reset the connection - await SafeCloseConnectionAsync(); - throw; + // Always ensure the connection is closed after the operation + await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context); } }