diff --git a/web/Areas/ClinicalScheduler/Services/InstructorScheduleService.cs b/web/Areas/ClinicalScheduler/Services/InstructorScheduleService.cs index 06b662743..898c527d2 100644 --- a/web/Areas/ClinicalScheduler/Services/InstructorScheduleService.cs +++ b/web/Areas/ClinicalScheduler/Services/InstructorScheduleService.cs @@ -1,3 +1,4 @@ +using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Viper.Classes.SQLContext; using Viper.Models.CTS; @@ -104,7 +105,7 @@ public async Task> GetInstructorScheduleAsync( _logger.LogInformation("Found {Count} instructor schedules", schedules.Count); return schedules; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving instructor schedules"); throw new InvalidOperationException("Failed to retrieve instructor schedules", ex); diff --git a/web/Areas/ClinicalScheduler/Services/PersonService.cs b/web/Areas/ClinicalScheduler/Services/PersonService.cs index f80665778..a407e0a3e 100644 --- a/web/Areas/ClinicalScheduler/Services/PersonService.cs +++ b/web/Areas/ClinicalScheduler/Services/PersonService.cs @@ -81,7 +81,7 @@ public PersonService(ILogger logger, ClinicalSchedulerContext con return person; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving person data for MothraId: {MothraId}", LogSanitizer.SanitizeId(mothraId)); throw new InvalidOperationException($"Failed to retrieve person data for MothraId {LogSanitizer.SanitizeId(mothraId)}", ex); @@ -139,7 +139,7 @@ public async Task> GetCliniciansByYearAsync(int year, _logger.LogInformation("Found {ClinicianCount} clinicians for year {Year} with person names from vPerson view", clinicians.Count, year); return clinicians; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving clinicians for year: {Year}", year); throw new InvalidOperationException($"Failed to retrieve clinicians for grad year {year}. Check database connectivity and view permissions.", ex); @@ -209,7 +209,7 @@ public async Task> GetCliniciansByGradYearRangeAsync(int _logger.LogError(ex, "Database error retrieving clinicians for grad year range {StartYear}-{EndYear}", LogSanitizer.SanitizeYear(startGradYear), LogSanitizer.SanitizeYear(endGradYear)); throw new InvalidOperationException($"Database error retrieving clinicians for grad year range {LogSanitizer.SanitizeYear(startGradYear)}-{LogSanitizer.SanitizeYear(endGradYear)}", ex); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving clinicians for grad year range {StartYear}-{EndYear}", LogSanitizer.SanitizeYear(startGradYear), LogSanitizer.SanitizeYear(endGradYear)); throw new InvalidOperationException($"Failed to retrieve clinicians for grad year range {LogSanitizer.SanitizeYear(startGradYear)}-{LogSanitizer.SanitizeYear(endGradYear)}", ex); @@ -240,7 +240,7 @@ public async Task> GetAllMothraIdsAsync(CancellationToken cancellat _logger.LogInformation("Found {Count} unique MothraIds in Clinical Scheduler data", mothraIds.Count); return mothraIds; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving unique MothraIds"); throw new InvalidOperationException("Failed to retrieve unique MothraIds from database", ex); @@ -277,7 +277,7 @@ public async Task> GetAllActiveEmployeeAffiliatesAsync(Ca _logger.LogDebug("Found {Count} active employee affiliates from AAUD", allAffiliates.Count); return allAffiliates; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving active employee affiliates from AAUD"); throw new InvalidOperationException("Failed to retrieve active employee affiliates from AAUD database", ex); @@ -325,7 +325,7 @@ public async Task> GetAllActiveEmployeeAffiliatesAsync(Ca return clinician; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving clinician data for MothraId: {MothraId} from AAUD", LogSanitizer.SanitizeId(mothraId)); throw new InvalidOperationException($"Failed to retrieve clinician data for MothraId {LogSanitizer.SanitizeId(mothraId)} from AAUD", ex); diff --git a/web/Areas/ClinicalScheduler/Services/RotationService.cs b/web/Areas/ClinicalScheduler/Services/RotationService.cs index 59f0a664e..7aaa8ef3f 100644 --- a/web/Areas/ClinicalScheduler/Services/RotationService.cs +++ b/web/Areas/ClinicalScheduler/Services/RotationService.cs @@ -1,3 +1,4 @@ +using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Viper.Areas.ClinicalScheduler.Extensions; using Viper.Areas.ClinicalScheduler.Models.DTOs.Responses; @@ -45,7 +46,7 @@ public async Task> GetRotationsAsync(CancellationToken cancell rotations.Count); return rotations.Select(r => r.ToDto()).ToList(); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving rotations from Clinical Scheduler"); throw new InvalidOperationException("Failed to retrieve rotations from Clinical Scheduler database", ex); @@ -82,7 +83,7 @@ public async Task> GetRotationsAsync(CancellationToken cancell return rotation?.ToDto(); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving rotation by ID: {RotationId}", rotationId); throw new InvalidOperationException($"Failed to retrieve rotation with ID {rotationId}", ex); @@ -124,7 +125,7 @@ public async Task> GetRotationsByCourseAsync(string courseNumber, return rotations; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving rotations by course - CourseNumber: {CourseNumber}, SubjectCode: {SubjectCode}", courseNumber, subjectCode); @@ -154,7 +155,7 @@ public async Task> GetRotationsByServiceAsync(int serviceId, C _logger.LogInformation("Retrieved {Count} rotations for service ID: {ServiceId}", rotations.Count, serviceId); return rotations.Select(r => r.ToDto()).ToList(); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving rotations by service ID: {ServiceId}", serviceId); throw new InvalidOperationException($"Failed to retrieve rotations for service ID {serviceId}", ex); @@ -180,7 +181,7 @@ public async Task> GetServicesAsync(CancellationToken cancellat _logger.LogInformation("Retrieved {Count} services from Clinical Scheduler", services.Count); return services.Select(s => s.ToDto()).ToList(); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving services from Clinical Scheduler"); throw new InvalidOperationException("Failed to retrieve services from Clinical Scheduler database", ex); @@ -215,7 +216,7 @@ public async Task> GetServicesAsync(CancellationToken cancellat return service?.ToDto(); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving service by ID: {ServiceId}", serviceId); throw new InvalidOperationException($"Failed to retrieve service with ID {serviceId}", ex); @@ -265,7 +266,7 @@ public async Task> GetInstructorSchedulesByRotationAsyn return schedules; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving instructor schedules for rotation ID: {RotationId}", rotationId); throw new InvalidOperationException($"Failed to retrieve instructor schedules for rotation ID {rotationId}", ex); diff --git a/web/Areas/ClinicalScheduler/Services/ScheduleAuditService.cs b/web/Areas/ClinicalScheduler/Services/ScheduleAuditService.cs index e0f5ec01a..9425aa642 100644 --- a/web/Areas/ClinicalScheduler/Services/ScheduleAuditService.cs +++ b/web/Areas/ClinicalScheduler/Services/ScheduleAuditService.cs @@ -1,3 +1,4 @@ +using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Viper.Classes.SQLContext; using Viper.Models.ClinicalScheduler; @@ -114,7 +115,7 @@ public async Task> GetInstructorScheduleAuditHistoryAsync( .OrderByDescending(a => a.TimeStamp) .ToListAsync(cancellationToken); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving audit history for instructor schedule {ScheduleId}", instructorScheduleId); throw new InvalidOperationException($"Failed to retrieve audit history for instructor schedule {instructorScheduleId}. Please try again or contact support if the problem persists.", ex); @@ -134,7 +135,7 @@ public async Task> GetRotationWeekAuditHistoryAsync( .OrderByDescending(a => a.TimeStamp) .ToListAsync(cancellationToken); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving audit history for rotation {RotationId}, week {WeekId}", rotationId, weekId); throw new InvalidOperationException($"Failed to retrieve audit history for rotation {rotationId}, week {weekId}. Please try again or contact support if the problem persists.", ex); @@ -179,7 +180,7 @@ private async Task CreateAuditEntryAsync( return auditEntry; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error creating audit entry for action {Action}, {MothraId} on rotation {RotationId}, week {WeekId}", action, LogSanitizer.SanitizeId(mothraId), rotationId, weekId); diff --git a/web/Areas/ClinicalScheduler/Services/ScheduleEditService.cs b/web/Areas/ClinicalScheduler/Services/ScheduleEditService.cs index f8a02c9e0..c8faa7dbd 100644 --- a/web/Areas/ClinicalScheduler/Services/ScheduleEditService.cs +++ b/web/Areas/ClinicalScheduler/Services/ScheduleEditService.cs @@ -1,3 +1,4 @@ +using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using Viper.Areas.ClinicalScheduler.EmailTemplates.Models; @@ -216,7 +217,9 @@ await _auditService.LogPrimaryEvaluatorSetAsync( } #pragma warning restore S3267 } +#pragma warning disable CA1031 // Intentional broad catch: post-transaction work (email/audit notifications) must not roll back the successful database changes above. catch (Exception postTransactionEx) +#pragma warning restore CA1031 { // Log warning but don't fail the operation - the database changes were successful _logger.LogWarning(postTransactionEx, "Post-transaction operations failed for instructor {MothraId} in rotation {RotationId}, but database changes were successful", @@ -238,7 +241,7 @@ await _auditService.LogPrimaryEvaluatorSetAsync( // Re-throw InvalidOperationException without wrapping (includes "already scheduled" messages) throw; } - catch (Exception saveEx) + catch (Exception saveEx) when (saveEx is DbUpdateException or SqlException) { _logger.LogError(saveEx, "Database save failed for MothraId='{MothraId}', RotationId={RotationId}, WeekIds=[{WeekIds}]", LogSanitizer.SanitizeId(mothraId), rotationId, string.Join(",", weekIds)); @@ -332,7 +335,9 @@ await _auditService.LogInstructorRemovedAsync( await HandlePrimaryEvaluatorRemovalAsync(schedule, currentUser.MothraId, cancellationToken); } } +#pragma warning disable CA1031 // Intentional broad catch: post-transaction work (email/audit notifications) must not roll back the successful database changes above. catch (Exception postTransactionEx) +#pragma warning restore CA1031 { // Log warning but don't fail the operation - the database changes were successful _logger.LogWarning(postTransactionEx, "Post-transaction operations failed for instructor removal {ScheduleId}, but database changes were successful", @@ -354,7 +359,7 @@ await _auditService.LogInstructorRemovedAsync( // Re-throw InvalidOperationException without wrapping (includes "Cannot remove primary evaluator" message) throw; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException) { _logger.LogError(ex, "Error removing instructor schedule {ScheduleId}", instructorScheduleId); throw new InvalidOperationException($"Failed to remove instructor schedule. Please try again or contact support if the problem persists.", ex); @@ -451,7 +456,9 @@ await _auditService.LogPrimaryEvaluatorSetAsync( await HandlePrimaryEvaluatorRemovalAsync(schedule, currentUser.MothraId, cancellationToken, null, requiresPrimaryEvaluator); } } +#pragma warning disable CA1031 // Intentional broad catch: post-transaction work (email/audit notifications) must not roll back the successful database changes above. catch (Exception postTransactionEx) +#pragma warning restore CA1031 { // Log warning but don't fail the operation - the database changes were successful _logger.LogWarning(postTransactionEx, "Post-transaction operations failed for primary evaluator update {ScheduleId}, but database changes were successful", @@ -463,7 +470,7 @@ await _auditService.LogPrimaryEvaluatorSetAsync( return (true, previousPrimaryName); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error setting primary evaluator for instructor schedule {ScheduleId} to {IsPrimary}", instructorScheduleId, isPrimary); throw new InvalidOperationException($"Failed to update primary evaluator status. Please try again or contact support if the problem persists.", ex); @@ -488,7 +495,7 @@ public async Task CanRemoveInstructorAsync( // All instructors can now be removed, including primary evaluators return true; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error checking if instructor schedule {ScheduleId} can be removed", instructorScheduleId); return false; @@ -530,7 +537,7 @@ public async Task> GetOtherRotationSchedulesAsync( return await query.ToListAsync(cancellationToken); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error checking other rotation schedules for {MothraId} on weeks {WeekIds} for grad year {GradYear}", LogSanitizer.SanitizeId(mothraId), string.Join(",", weekIds), LogSanitizer.SanitizeYear(gradYear)); @@ -558,7 +565,7 @@ public async Task> GetScheduledInstructorsAsync( .Where(s => s.RotationId == rotationId && weekIds.Contains(s.WeekId)) .ToListAsync(cancellationToken); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error getting scheduled instructors for rotation {RotationId} on weeks {WeekIds}", rotationId, string.Join(",", weekIds)); throw new InvalidOperationException($"Failed to retrieve scheduled instructors. Please try again or contact support if the problem persists.", ex); @@ -661,7 +668,7 @@ private async Task SendPrimaryEvaluatorRemovedNotificationAsync(InstructorSchedu } } } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogWarning(ex, "Could not retrieve instructor name for {MothraId} in email notification", LogSanitizer.SanitizeId(schedule.MothraId)); } @@ -694,7 +701,7 @@ await _context.Entry(schedule) weekNumber = weekGradYear.WeekNum.ToString(); } } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogWarning(ex, "Could not retrieve week number for {WeekId} in email notification", schedule.WeekId); } @@ -719,7 +726,7 @@ await _context.Entry(schedule) : ""; } } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogWarning(ex, "Could not retrieve modifier information for {MothraId} in email notification", modifiedByMothraId); } @@ -770,9 +777,10 @@ await _emailService.SendEmailAsync( _logger.LogInformation("No notification recipients configured for Primary Evaluator Removal; skipped email. Rotation={RotationName}, Week={WeekNumber}", rotationName, weekNumber); } } +#pragma warning disable CA1031 // Intentional broad catch: email notification is secondary to the schedule removal; any failure must be logged but not propagated. catch (Exception ex) +#pragma warning restore CA1031 { - // Log error but don't fail the transaction - email is secondary to the schedule removal _logger.LogError(ex, "Failed to send primary evaluator removal notification for {MothraId} from rotation {RotationId} week {WeekId} (rotation: {RotationName})", LogSanitizer.SanitizeId(schedule.MothraId), schedule.RotationId, schedule.WeekId, schedule.Rotation?.Name ?? "Unknown"); } diff --git a/web/Areas/ClinicalScheduler/Services/SchedulePermissionService.cs b/web/Areas/ClinicalScheduler/Services/SchedulePermissionService.cs index 660729fd0..1cc46970f 100644 --- a/web/Areas/ClinicalScheduler/Services/SchedulePermissionService.cs +++ b/web/Areas/ClinicalScheduler/Services/SchedulePermissionService.cs @@ -1,3 +1,4 @@ +using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Viper.Classes.SQLContext; using Viper.Models.AAUD; @@ -87,7 +88,7 @@ public async Task HasEditPermissionForServiceAsync(int serviceId, Cancella return hasPermission; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { var currentUser = _userHelper.GetCurrentUser(); _logger.LogError(ex, "Error checking edit permissions for user {MothraId} and service {ServiceId}", LogSanitizer.SanitizeId(currentUser?.MothraId), serviceId); @@ -114,7 +115,7 @@ public async Task HasEditPermissionForRotationAsync(int rotationId, Cancel return await HasEditPermissionForServiceAsync(rotation.ServiceId, cancellationToken); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { var user = _userHelper.GetCurrentUser(); _logger.LogError(ex, "Error checking edit permissions for user {MothraId} and rotation {RotationId}", LogSanitizer.SanitizeId(user?.MothraId), rotationId); @@ -150,7 +151,7 @@ public async Task> GetUserEditableServicesAsync(CancellationToken return editableServices; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { var user = _userHelper.GetCurrentUser(); _logger.LogError(ex, "Error getting editable services for user {MothraId}", LogSanitizer.SanitizeId(user?.MothraId)); @@ -183,7 +184,7 @@ public async Task> GetUserServicePermissionsAsync(Cancella return permissions; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { var user = _userHelper.GetCurrentUser(); _logger.LogError(ex, "Error getting service permissions for user {MothraId}", LogSanitizer.SanitizeId(user?.MothraId)); @@ -212,7 +213,7 @@ public async Task GetRequiredPermissionForServiceAsync(int serviceId, Ca _logger.LogDebug("Required permission for service {ServiceId}: {RequiredPermission}", serviceId, requiredPermission); return requiredPermission; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error getting required permission for service {ServiceId}", serviceId); return ClinicalSchedulePermissions.Manage; @@ -258,7 +259,7 @@ public async Task CanEditOwnScheduleAsync(int instructorScheduleId, Cancel return canEdit; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { var user = _userHelper.GetCurrentUser(); _logger.LogError(ex, "Error checking own schedule permissions for user {MothraId} and instructor schedule {InstructorScheduleId}", @@ -304,7 +305,7 @@ public Task CheckStudentScheduleParamsAsync(string? mothraId, int? rotatio _logger.LogDebug("User {MothraId} denied access to student schedules", LogSanitizer.SanitizeId(user.MothraId)); return Task.FromResult(false); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { var user = _userHelper.GetCurrentUser(); _logger.LogError(ex, "Error checking student schedule access for user {MothraId}", LogSanitizer.SanitizeId(user?.MothraId)); @@ -346,7 +347,7 @@ public Task CheckInstructorScheduleParamsAsync(string? mothraId, int? rota _logger.LogDebug("User {MothraId} denied access to instructor schedules", LogSanitizer.SanitizeId(user.MothraId)); return Task.FromResult(false); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { var user = _userHelper.GetCurrentUser(); _logger.LogError(ex, "Error checking instructor schedule access for user {MothraId}", LogSanitizer.SanitizeId(user?.MothraId)); diff --git a/web/Areas/ClinicalScheduler/Services/StudentScheduleService.cs b/web/Areas/ClinicalScheduler/Services/StudentScheduleService.cs index 5b2e9b93b..67d1c7795 100644 --- a/web/Areas/ClinicalScheduler/Services/StudentScheduleService.cs +++ b/web/Areas/ClinicalScheduler/Services/StudentScheduleService.cs @@ -1,3 +1,4 @@ +using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Viper.Areas.CTS.Models; using Viper.Classes.SQLContext; @@ -110,7 +111,7 @@ public async Task> GetStudentScheduleAsync( _logger.LogInformation("Found {Count} student schedules", result.Count); return result; } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving student schedules"); throw new InvalidOperationException("Failed to retrieve student schedules", ex); diff --git a/web/Areas/ClinicalScheduler/Services/WeekService.cs b/web/Areas/ClinicalScheduler/Services/WeekService.cs index 00ed34165..efd0450a4 100644 --- a/web/Areas/ClinicalScheduler/Services/WeekService.cs +++ b/web/Areas/ClinicalScheduler/Services/WeekService.cs @@ -1,3 +1,4 @@ +using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Viper.Areas.ClinicalScheduler.Extensions; using Viper.Areas.ClinicalScheduler.Models.DTOs.Responses; @@ -48,7 +49,7 @@ public async Task> GetWeeksAsync(int gradYear, bool includeExtende weeks.Count, gradYear, includeExtendedRotation); return weeks.ToDto(); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving weeks for grad year {GradYear}: {ErrorMessage}", gradYear, ex.Message); throw new InvalidOperationException($"Failed to retrieve weeks for graduation year {gradYear}", ex); @@ -89,7 +90,7 @@ public async Task> GetWeeksAsync(int gradYear, bool includeExtende weekId, week.GradYear, week.WeekNum); return week.ToDto(); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving week {WeekId} for grad year {GradYear}", weekId, gradYear); throw new InvalidOperationException($"Failed to retrieve week {weekId} for graduation year {gradYear}", ex); @@ -130,7 +131,7 @@ public async Task> GetWeeksAsync(int gradYear, bool includeExtende _logger.LogInformation("Current week is {WeekNum} for grad year {GradYear}", week.WeekNum, week.GradYear); return week.ToDto(); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving current week for grad year {GradYear}", gradYear); throw new InvalidOperationException($"Failed to retrieve current week for graduation year {gradYear}", ex); @@ -174,7 +175,7 @@ public async Task> GetWeeksByDateRangeAsync(DateTime? startDate = weeks.Count, startDate?.ToString("yyyy-MM-dd") ?? "none", endDate?.ToString("yyyy-MM-dd") ?? "none"); return weeks.ToDto(); } - catch (Exception ex) + catch (Exception ex) when (ex is DbUpdateException or SqlException or InvalidOperationException) { _logger.LogError(ex, "Error retrieving weeks for date range {StartDate} to {EndDate}", startDate?.ToString("yyyy-MM-dd") ?? "none", endDate?.ToString("yyyy-MM-dd") ?? "none");