diff --git a/backend/api.test/Services/RobotService.cs b/backend/api.test/Services/RobotService.cs index 5d26c11e..6e4672b6 100644 --- a/backend/api.test/Services/RobotService.cs +++ b/backend/api.test/Services/RobotService.cs @@ -52,7 +52,7 @@ public async Task CheckThatReadByIdReturnsCorrectRobot() var installation = await DatabaseUtilities.NewInstallation(); var robot = await DatabaseUtilities.NewRobot(RobotStatus.Available, installation); - var robotById = await RobotService.ReadById(robot.Id, readOnly: false); + var robotById = await RobotService.ReadById(robot.Id, readOnly: true); Assert.Equal(robot.Id, robotById!.Id); } diff --git a/backend/api/Controllers/InspectionAreaController.cs b/backend/api/Controllers/InspectionAreaController.cs index 814eb183..6e52cadc 100644 --- a/backend/api/Controllers/InspectionAreaController.cs +++ b/backend/api/Controllers/InspectionAreaController.cs @@ -252,7 +252,7 @@ [FromBody] CreateDefaultLocalizationPose newDefaultLocalizationPose { var inspectionArea = await inspectionAreaService.ReadById( inspectionAreaId, - readOnly: false + readOnly: true ); if (inspectionArea is null) { diff --git a/backend/api/Controllers/MissionDefinitionController.cs b/backend/api/Controllers/MissionDefinitionController.cs index ba9b9f86..ff295a7c 100644 --- a/backend/api/Controllers/MissionDefinitionController.cs +++ b/backend/api/Controllers/MissionDefinitionController.cs @@ -147,7 +147,7 @@ [FromBody] UpdateMissionDefinitionQuery missionDefinitionQuery return BadRequest("Invalid data."); } - var missionDefinition = await missionDefinitionService.ReadById(id, readOnly: false); + var missionDefinition = await missionDefinitionService.ReadById(id, readOnly: true); if (missionDefinition == null) { return NotFound($"Could not find mission definition with id '{id}'"); @@ -198,7 +198,7 @@ [FromBody] UpdateMissionDefinitionIsDeprecatedQuery missionDefinitionIsDeprecate return BadRequest("Invalid data."); } - var missionDefinition = await missionDefinitionService.ReadById(id, readOnly: false); + var missionDefinition = await missionDefinitionService.ReadById(id, readOnly: true); if (missionDefinition == null) { return NotFound($"Could not find mission definition with id '{id}'"); diff --git a/backend/api/EventHandlers/MissionEventHandler.cs b/backend/api/EventHandlers/MissionEventHandler.cs index 10d06fa2..26b00259 100644 --- a/backend/api/EventHandlers/MissionEventHandler.cs +++ b/backend/api/EventHandlers/MissionEventHandler.cs @@ -89,6 +89,14 @@ private async void OnMissionRunCreated(object? sender, MissionRunCreatedEventArg private async void OnRobotAvailable(object? sender, RobotAvailableEventArgs e) { + if (e.Robot.Status != RobotStatus.Available) + { + _logger.LogWarning( + "OnRobotAvailable was triggered while robot was {robotStatus}", + e.Robot.Status + ); + return; + } _startMissionSemaphore.WaitOne(); try { diff --git a/backend/api/EventHandlers/MqttEventHandler.cs b/backend/api/EventHandlers/MqttEventHandler.cs index 880e20b8..8d8f0e90 100644 --- a/backend/api/EventHandlers/MqttEventHandler.cs +++ b/backend/api/EventHandlers/MqttEventHandler.cs @@ -454,7 +454,7 @@ await MissionRunService.UpdateMissionRunStatusByIsarMissionId( if (updatedFlotillaMissionRun.MissionId == null) { _logger.LogInformation( - "Mission run {missionRunId} does not have a mission definition assosiated with it", + "Mission run {missionRunId} does not have a mission definition associated with it", updatedFlotillaMissionRun.Id ); return; diff --git a/backend/api/Services/AccessRoleService.cs b/backend/api/Services/AccessRoleService.cs index 7da9bd20..ec6c9f1e 100644 --- a/backend/api/Services/AccessRoleService.cs +++ b/backend/api/Services/AccessRoleService.cs @@ -18,7 +18,7 @@ RoleAccessLevel accessLevel ); public Task ReadByInstallation(Installation installation); public Task> ReadAll(); - public void DetachTracking(AccessRole accessRole); + public void DetachTracking(FlotillaDbContext context, AccessRole accessRole); } public class AccessRoleService( @@ -101,7 +101,7 @@ RoleAccessLevel accessLevel await context.AccessRoles.AddAsync(newAccessRole); await context.SaveChangesAsync(); - DetachTracking(newAccessRole); + DetachTracking(context, newAccessRole); return newAccessRole!; } @@ -135,7 +135,7 @@ public bool IsAuthenticationAvailable() return httpContextAccessor.HttpContext != null; } - public void DetachTracking(AccessRole accessRole) + public void DetachTracking(FlotillaDbContext context, AccessRole accessRole) { context.Entry(accessRole).State = EntityState.Detached; } diff --git a/backend/api/Services/AreaService.cs b/backend/api/Services/AreaService.cs index c14ff8d7..05bd3c40 100644 --- a/backend/api/Services/AreaService.cs +++ b/backend/api/Services/AreaService.cs @@ -35,7 +35,7 @@ public Task> ReadAll( public Task Delete(string id); - public void DetachTracking(Area area); + public void DetachTracking(FlotillaDbContext context, Area area); } [SuppressMessage( @@ -210,7 +210,7 @@ await inspectionAreaService.ReadByInstallationAndPlantAndName( await context.Areas.AddAsync(newArea); await ApplyDatabaseUpdate(installation); - DetachTracking(newArea); + DetachTracking(context, newArea); return newArea; } @@ -218,6 +218,7 @@ public async Task Update(Area area) { var entry = context.Update(area); await ApplyDatabaseUpdate(area.Installation); + DetachTracking(context, area); return entry.Entity; } @@ -352,16 +353,19 @@ AreaQueryStringParameters parameters return Expression.Lambda>(body, area); } - public void DetachTracking(Area area) + public void DetachTracking(FlotillaDbContext context, Area area) { if (area.Installation != null) - installationService.DetachTracking(area.Installation); + installationService.DetachTracking(context, area.Installation); if (area.Plant != null) - plantService.DetachTracking(area.Plant); + plantService.DetachTracking(context, area.Plant); if (area.InspectionArea != null) - inspectionAreaService.DetachTracking(area.InspectionArea); + inspectionAreaService.DetachTracking(context, area.InspectionArea); if (area.DefaultLocalizationPose != null) - defaultLocalizationPoseService.DetachTracking(area.DefaultLocalizationPose); + defaultLocalizationPoseService.DetachTracking( + context, + area.DefaultLocalizationPose + ); context.Entry(area).State = EntityState.Detached; } } diff --git a/backend/api/Services/DefaultLocalizationPoseService.cs b/backend/api/Services/DefaultLocalizationPoseService.cs index 6058a9f3..8202ec0d 100644 --- a/backend/api/Services/DefaultLocalizationPoseService.cs +++ b/backend/api/Services/DefaultLocalizationPoseService.cs @@ -21,7 +21,10 @@ DefaultLocalizationPose defaultLocalizationPose public abstract Task Delete(string id); - public void DetachTracking(DefaultLocalizationPose defaultLocalizationPose); + public void DetachTracking( + FlotillaDbContext context, + DefaultLocalizationPose defaultLocalizationPose + ); } [System.Diagnostics.CodeAnalysis.SuppressMessage( @@ -59,7 +62,7 @@ DefaultLocalizationPose defaultLocalizationPose await context.DefaultLocalizationPoses.AddAsync(defaultLocalizationPose); await context.SaveChangesAsync(); - DetachTracking(defaultLocalizationPose); + DetachTracking(context, defaultLocalizationPose); return defaultLocalizationPose; } @@ -69,6 +72,7 @@ DefaultLocalizationPose defaultLocalizationPose { var entry = context.Update(defaultLocalizationPose); await context.SaveChangesAsync(); + DetachTracking(context, defaultLocalizationPose); return entry.Entity; } @@ -87,7 +91,10 @@ DefaultLocalizationPose defaultLocalizationPose return defaultLocalizationPose; } - public void DetachTracking(DefaultLocalizationPose defaultLocalizationPose) + public void DetachTracking( + FlotillaDbContext context, + DefaultLocalizationPose defaultLocalizationPose + ) { context.Entry(defaultLocalizationPose).State = EntityState.Detached; } diff --git a/backend/api/Services/InspectionAreaService.cs b/backend/api/Services/InspectionAreaService.cs index f1190bb0..408ee3f5 100644 --- a/backend/api/Services/InspectionAreaService.cs +++ b/backend/api/Services/InspectionAreaService.cs @@ -38,7 +38,7 @@ public Task> ReadByInstallation( public Task Delete(string id); - public void DetachTracking(InspectionArea inspectionArea); + public void DetachTracking(FlotillaDbContext context, InspectionArea inspectionArea); } [SuppressMessage( @@ -194,7 +194,7 @@ await plantService.ReadByInstallationAndPlantCode( inspectionArea.Installation, new InspectionAreaResponse(inspectionArea) ); - DetachTracking(inspectionArea); + DetachTracking(context, inspectionArea); return inspectionArea!; } @@ -207,6 +207,7 @@ public async Task Update(InspectionArea inspectionArea) inspectionArea.Installation, new InspectionAreaResponse(inspectionArea) ); + DetachTracking(context, inspectionArea); return entry.Entity; } @@ -263,14 +264,25 @@ private async Task ApplyDatabaseUpdate(Installation? installation) ); } - public void DetachTracking(InspectionArea inspectionArea) + public void DetachTracking(FlotillaDbContext context, InspectionArea inspectionArea) { - if (inspectionArea.Installation != null) - installationService.DetachTracking(inspectionArea.Installation); - if (inspectionArea.Plant != null) - plantService.DetachTracking(inspectionArea.Plant); - if (inspectionArea.DefaultLocalizationPose != null) + if ( + inspectionArea.Installation != null + && context.Entry(inspectionArea.Installation).State != EntityState.Detached + ) + installationService.DetachTracking(context, inspectionArea.Installation); + if ( + inspectionArea.Plant != null + && context.Entry(inspectionArea.Plant).State != EntityState.Detached + ) + plantService.DetachTracking(context, inspectionArea.Plant); + if ( + inspectionArea.DefaultLocalizationPose != null + && context.Entry(inspectionArea.DefaultLocalizationPose).State + != EntityState.Detached + ) defaultLocalizationPoseService.DetachTracking( + context, inspectionArea.DefaultLocalizationPose ); context.Entry(inspectionArea).State = EntityState.Detached; diff --git a/backend/api/Services/InspectionService.cs b/backend/api/Services/InspectionService.cs index 7b8e2dbc..61ad6805 100644 --- a/backend/api/Services/InspectionService.cs +++ b/backend/api/Services/InspectionService.cs @@ -60,7 +60,7 @@ public async Task UpdateInspectionStatus( IsarTaskStatus isarTaskStatus ) { - var inspection = await ReadByIsarTaskId(isarTaskId, readOnly: false); + var inspection = await ReadByIsarTaskId(isarTaskId, readOnly: true); if (inspection is null) { string errorMessage = $"Inspection with task ID {isarTaskId} could not be found"; @@ -69,7 +69,7 @@ IsarTaskStatus isarTaskStatus } inspection.UpdateStatus(isarTaskStatus); - inspection = await Update(inspection); + await Update(inspection); return inspection; } @@ -89,7 +89,7 @@ private async Task ApplyDatabaseUpdate(Installation? installation) ); } - private async Task Update(Inspection inspection) + private async Task Update(Inspection inspection) { var entry = context.Update(inspection); @@ -107,8 +107,7 @@ private async Task Update(Inspection inspection) var installation = missionRun?.InspectionArea?.Installation; await ApplyDatabaseUpdate(installation); - - return entry.Entity; + DetachTracking(context, inspection); } public async Task ReadByIsarTaskId(string id, bool readOnly = true) @@ -136,7 +135,7 @@ private IQueryable GetInspections(bool readOnly = true) string isarTaskId ) { - var inspection = await ReadByIsarTaskId(isarTaskId, readOnly: false); + var inspection = await ReadByIsarTaskId(isarTaskId, readOnly: true); if (inspection is null) { @@ -151,7 +150,7 @@ string isarTaskId }; inspection.InspectionFindings.Add(inspectionFinding); - inspection = await Update(inspection); + await Update(inspection); return inspection; } @@ -227,5 +226,14 @@ await response.Content.ReadFromJsonAsync() ); return null; } + + public void DetachTracking(FlotillaDbContext context, Inspection inspection) + { + foreach (var inspectionFinding in inspection.InspectionFindings) + { + context.Entry(inspectionFinding).State = EntityState.Detached; + } + context.Entry(inspection).State = EntityState.Detached; + } } } diff --git a/backend/api/Services/InstallationService.cs b/backend/api/Services/InstallationService.cs index 76a1cbcb..721e46ff 100644 --- a/backend/api/Services/InstallationService.cs +++ b/backend/api/Services/InstallationService.cs @@ -23,7 +23,7 @@ public interface IInstallationService public abstract Task Delete(string id); - public void DetachTracking(Installation installation); + public void DetachTracking(FlotillaDbContext context, Installation installation); } [System.Diagnostics.CodeAnalysis.SuppressMessage( @@ -109,7 +109,7 @@ public async Task Create(CreateInstallationQuery newInstallationQu }; await context.Installations.AddAsync(installation); await ApplyUnprotectedDatabaseUpdate(); - DetachTracking(installation); + DetachTracking(context, installation); } return installation; @@ -119,6 +119,7 @@ public async Task Update(Installation installation) { var entry = context.Update(installation); await ApplyDatabaseUpdate(installation); + DetachTracking(context, installation); return entry.Entity; } @@ -136,7 +137,7 @@ public async Task Update(Installation installation) return installation; } - public void DetachTracking(Installation installation) + public void DetachTracking(FlotillaDbContext context, Installation installation) { context.Entry(installation).State = EntityState.Detached; } diff --git a/backend/api/Services/MissionDefinitionService.cs b/backend/api/Services/MissionDefinitionService.cs index 4dfdedf5..e05e952d 100644 --- a/backend/api/Services/MissionDefinitionService.cs +++ b/backend/api/Services/MissionDefinitionService.cs @@ -39,7 +39,7 @@ string missionDefinitionId public Task Delete(string id); - public void DetachTracking(MissionDefinition missionDefinition); + public void DetachTracking(FlotillaDbContext context, MissionDefinition missionDefinition); } [SuppressMessage( @@ -84,7 +84,7 @@ public async Task Create(MissionDefinition missionDefinition) missionDefinition.InspectionArea?.Installation, new MissionDefinitionResponse(missionDefinition) ); - DetachTracking(missionDefinition); + DetachTracking(context, missionDefinition); return missionDefinition; } @@ -192,6 +192,7 @@ public async Task Update(MissionDefinition missionDefinition) missionDefinition?.InspectionArea?.Installation, missionDefinition != null ? new MissionDefinitionResponse(missionDefinition) : null ); + DetachTracking(context, missionDefinition!); return entry.Entity; } @@ -327,12 +328,12 @@ parameters.InstallationCode is null ); } - public void DetachTracking(MissionDefinition missionDefinition) + public void DetachTracking(FlotillaDbContext context, MissionDefinition missionDefinition) { if (missionDefinition.LastSuccessfulRun != null) - missionRunService.DetachTracking(missionDefinition.LastSuccessfulRun); + missionRunService.DetachTracking(context, missionDefinition.LastSuccessfulRun); if (missionDefinition.Source != null) - sourceService.DetachTracking(missionDefinition.Source); + sourceService.DetachTracking(context, missionDefinition.Source); context.Entry(missionDefinition).State = EntityState.Detached; } } diff --git a/backend/api/Services/MissionRunService.cs b/backend/api/Services/MissionRunService.cs index 4034543f..dfb889e5 100644 --- a/backend/api/Services/MissionRunService.cs +++ b/backend/api/Services/MissionRunService.cs @@ -88,7 +88,7 @@ string failureDescription public Task UpdateCurrentRobotMissionToFailed(string robotId); - public void DetachTracking(MissionRun missionRun); + public void DetachTracking(FlotillaDbContext context, MissionRun missionRun); } [SuppressMessage( @@ -143,7 +143,7 @@ public async Task Create( new MissionRunResponse(missionRun) ); - DetachTracking(missionRun); + DetachTracking(context, missionRun); if (triggerCreatedMissionRunEvent) { @@ -296,13 +296,21 @@ public bool IncludesUnsupportedInspectionType(MissionRun missionRun) ); } - public async Task Update(MissionRun missionRun) + public async Task Update(MissionRun missionRun) { - context.Entry(missionRun.Robot).State = EntityState.Unchanged; + if (missionRun.Robot is not null) + { + context.Entry(missionRun.Robot).State = EntityState.Unchanged; + } if (missionRun.InspectionArea is not null) { context.Entry(missionRun.InspectionArea).State = EntityState.Unchanged; } + foreach (var task in missionRun.Tasks) + { + if (task.Inspection != null) + context.Entry(task.Inspection).State = EntityState.Unchanged; + } var entry = context.Update(missionRun); await ApplyDatabaseUpdate(missionRun.InspectionArea?.Installation); @@ -311,8 +319,7 @@ public async Task Update(MissionRun missionRun) missionRun?.InspectionArea?.Installation, missionRun != null ? new MissionRunResponse(missionRun) : null ); - DetachTracking(missionRun!); - return entry.Entity; + DetachTracking(context, missionRun!); } public async Task Delete(string id) @@ -630,7 +637,7 @@ public async Task UpdateMissionRunType( MissionRunType missionRunType ) { - var missionRun = await ReadById(missionRunId, readOnly: false); + var missionRun = await ReadById(missionRunId, readOnly: true); if (missionRun is null) { string errorMessage = $"Mission with mission Id {missionRunId} was not found"; @@ -646,7 +653,7 @@ public async Task UpdateMissionRunStatusByIsarMissionId( MissionStatus missionStatus ) { - var missionRun = await ReadByIsarMissionId(isarMissionId, readOnly: false); + var missionRun = await ReadByIsarMissionId(isarMissionId, readOnly: true); if (missionRun is null) { string errorMessage = $"Mission with isar mission Id {isarMissionId} was not found"; @@ -656,11 +663,7 @@ MissionStatus missionStatus missionRun.Status = missionStatus; - missionRun = await UpdateMissionRunProperty( - missionRun.Id, - "MissionStatus", - missionStatus - ); + missionRun = await UpdateMissionRunProperty(missionRun.Id, "Status", missionStatus); if (missionRun.Status == MissionStatus.Failed) { @@ -682,7 +685,7 @@ public async Task UpdateMissionRunProperty( object? value ) { - var missionRun = await ReadById(missionRunId, readOnly: false); + var missionRun = await ReadById(missionRunId, readOnly: true); if (missionRun is null) { string errorMessage = @@ -708,7 +711,7 @@ public async Task UpdateMissionRunProperty( try { - missionRun = await Update(missionRun); + await Update(missionRun); } catch (InvalidOperationException e) { @@ -754,7 +757,7 @@ string failureDescription ) { var missionRun = - await ReadById(missionRunId, readOnly: false) + await ReadById(missionRunId, readOnly: true) ?? throw new MissionRunNotFoundException( $"Could not find mission run with ID {missionRunId}" ); @@ -770,20 +773,28 @@ await ReadById(missionRunId, readOnly: false) task.Inspection.Status = InspectionStatus.Failed; } } - return await Update(missionRun); + await Update(missionRun); + return missionRun; } - public void DetachTracking(MissionRun missionRun) + public void DetachTracking(FlotillaDbContext context, MissionRun missionRun) { + context.Entry(missionRun).State = EntityState.Detached; foreach (var task in missionRun.Tasks) { - missionTaskService.DetachTracking(task); + if (context.Entry(task).State != EntityState.Detached) + missionTaskService.DetachTracking(context, task); } - if (missionRun.InspectionArea != null) - inspectionAreaService.DetachTracking(missionRun.InspectionArea); - if (missionRun.Robot != null) - robotService.DetachTracking(missionRun.Robot); - context.Entry(missionRun).State = EntityState.Detached; + if ( + missionRun.InspectionArea != null + && context.Entry(missionRun.InspectionArea).State != EntityState.Detached + ) + inspectionAreaService.DetachTracking(context, missionRun.InspectionArea); + if ( + missionRun.Robot != null + && context.Entry(missionRun.Robot).State != EntityState.Detached + ) + robotService.DetachTracking(context, missionRun.Robot); } public async Task UpdateWithIsarInfo( @@ -792,7 +803,7 @@ IsarMission isarMission ) { var missionRun = - await ReadById(missionRunId, readOnly: false) + await ReadById(missionRunId, readOnly: true) ?? throw new MissionRunNotFoundException( $"Could not find mission run with ID {missionRunId}" ); @@ -803,7 +814,8 @@ await ReadById(missionRunId, readOnly: false) var task = missionRun.GetTaskByIsarId(isarTask.IsarTaskId); task?.UpdateWithIsarInfo(isarTask); } - return await Update(missionRun); + await Update(missionRun); + return missionRun; } } } diff --git a/backend/api/Services/MissionSchedulingService.cs b/backend/api/Services/MissionSchedulingService.cs index 6eafcfca..a0a27ecb 100644 --- a/backend/api/Services/MissionSchedulingService.cs +++ b/backend/api/Services/MissionSchedulingService.cs @@ -524,20 +524,10 @@ await missionRunService.Create( private async Task StartMissionRun(MissionRun queuedMissionRun, Robot robot) { - string missionRunId = queuedMissionRun.Id; - - var missionRun = await missionRunService.ReadById(missionRunId, readOnly: true); - if (missionRun == null) - { - string errorMessage = $"Could not find mission run with id {missionRunId}"; - logger.LogError("{Message}", errorMessage); - throw new MissionRunNotFoundException(errorMessage); - } - IsarMission isarMission; try { - isarMission = await isarService.StartMission(robot, missionRun); + isarMission = await isarService.StartMission(robot, queuedMissionRun); } catch (HttpRequestException e) { @@ -559,16 +549,16 @@ private async Task StartMissionRun(MissionRun queuedMissionRun, Robot robot) throw new IsarCommunicationException(ErrorMessage); } - await missionRunService.UpdateWithIsarInfo(missionRun.Id, isarMission); + await missionRunService.UpdateWithIsarInfo(queuedMissionRun.Id, isarMission); await missionRunService.UpdateMissionRunProperty( - missionRun.Id, + queuedMissionRun.Id, "Status", MissionStatus.Ongoing ); robot.Status = RobotStatus.Busy; await robotService.UpdateRobotStatus(robot.Id, RobotStatus.Busy); - await robotService.UpdateCurrentMissionId(robot.Id, missionRun.Id); + await robotService.UpdateCurrentMissionId(robot.Id, queuedMissionRun.Id); logger.LogInformation("Started mission run '{Id}'", queuedMissionRun.Id); } diff --git a/backend/api/Services/MissionTaskService.cs b/backend/api/Services/MissionTaskService.cs index 72ee2c75..61e9a6a9 100644 --- a/backend/api/Services/MissionTaskService.cs +++ b/backend/api/Services/MissionTaskService.cs @@ -14,7 +14,7 @@ public Task UpdateMissionTaskStatus( IsarTaskStatus isarTaskStatus ); - public void DetachTracking(MissionTask missionTask); + public void DetachTracking(FlotillaDbContext context, MissionTask missionTask); } [SuppressMessage( @@ -30,7 +30,7 @@ public async Task UpdateMissionTaskStatus( IsarTaskStatus isarTaskStatus ) { - var missionTask = await ReadByIsarTaskId(isarTaskId, readOnly: false); + var missionTask = await ReadByIsarTaskId(isarTaskId, readOnly: true); if (missionTask is null) { string errorMessage = $"Inspection with ID {isarTaskId} could not be found"; @@ -49,6 +49,7 @@ private async Task Update(MissionTask missionTask) var entry = context.Update(missionTask); await context.SaveChangesAsync(); + DetachTracking(context, missionTask); return entry.Entity; } @@ -71,9 +72,11 @@ private IQueryable GetMissionTasks(bool readOnly = true) ); } - public void DetachTracking(MissionTask missionTask) + public void DetachTracking(FlotillaDbContext context, MissionTask missionTask) { context.Entry(missionTask).State = EntityState.Detached; + if (missionTask.Inspection != null) + context.Entry(missionTask.Inspection).State = EntityState.Detached; } } } diff --git a/backend/api/Services/PlantService.cs b/backend/api/Services/PlantService.cs index 2c469887..c4f3d23c 100644 --- a/backend/api/Services/PlantService.cs +++ b/backend/api/Services/PlantService.cs @@ -39,7 +39,7 @@ public Task> ReadByInstallation( public Task Delete(string id); - public void DetachTracking(Plant plant); + public void DetachTracking(FlotillaDbContext context, Plant plant); } [SuppressMessage( @@ -158,7 +158,7 @@ await installationService.ReadByInstallationCode( context.Entry(plant.Installation).State = EntityState.Unchanged; await context.Plants.AddAsync(plant); await ApplyDatabaseUpdate(plant.Installation); - DetachTracking(plant); + DetachTracking(context, plant); } return plant!; } @@ -167,6 +167,7 @@ public async Task Update(Plant plant) { var entry = context.Update(plant); await ApplyDatabaseUpdate(plant.Installation); + DetachTracking(context, plant); return entry.Entity; } @@ -214,10 +215,10 @@ private async Task ApplyDatabaseUpdate(Installation? installation) ); } - public void DetachTracking(Plant plant) + public void DetachTracking(FlotillaDbContext context, Plant plant) { if (plant.Installation != null) - installationService.DetachTracking(plant.Installation); + installationService.DetachTracking(context, plant.Installation); context.Entry(plant).State = EntityState.Detached; } } diff --git a/backend/api/Services/RobotModelService.cs b/backend/api/Services/RobotModelService.cs index 0cb01073..f66612a2 100644 --- a/backend/api/Services/RobotModelService.cs +++ b/backend/api/Services/RobotModelService.cs @@ -21,7 +21,7 @@ public interface IRobotModelService public abstract Task Delete(string id); - public void DetachTracking(RobotModel robotModel); + public void DetachTracking(FlotillaDbContext context, RobotModel robotModel); } [System.Diagnostics.CodeAnalysis.SuppressMessage( @@ -76,7 +76,7 @@ public async Task Create(RobotModel newRobotModel) { await _context.RobotModels.AddAsync(newRobotModel); await _context.SaveChangesAsync(); - DetachTracking(newRobotModel); + DetachTracking(_context, newRobotModel); return newRobotModel; } @@ -84,6 +84,7 @@ public async Task Update(RobotModel robotModel) { var entry = _context.Update(robotModel); await _context.SaveChangesAsync(); + DetachTracking(_context, robotModel); return entry.Entity; } @@ -101,7 +102,7 @@ public async Task Update(RobotModel robotModel) return robotModel; } - public void DetachTracking(RobotModel robotModel) + public void DetachTracking(FlotillaDbContext context, RobotModel robotModel) { _context.Entry(robotModel).State = EntityState.Detached; } diff --git a/backend/api/Services/RobotService.cs b/backend/api/Services/RobotService.cs index 56d2ff7b..6d13b85c 100644 --- a/backend/api/Services/RobotService.cs +++ b/backend/api/Services/RobotService.cs @@ -35,7 +35,7 @@ public Task> ReadRobotsForInstallation( public Task UpdateMissionQueueFrozen(string robotId, bool missionQueueFrozen); public Task UpdateFlotillaStatus(string robotId, RobotFlotillaStatus status); public Task Delete(string id); - public void DetachTracking(Robot robot); + public void DetachTracking(FlotillaDbContext context, Robot robot); } [SuppressMessage( @@ -64,7 +64,7 @@ public async Task Create(Robot newRobot) await context.Robots.AddAsync(newRobot); await ApplyDatabaseUpdate(newRobot.CurrentInstallation); - DetachTracking(newRobot); + DetachTracking(context, newRobot); return newRobot; } @@ -128,7 +128,7 @@ public async Task CreateFromQuery(CreateRobotQuery robotQuery) newRobot!.CurrentInstallation, new RobotResponse(newRobot!) ); - DetachTracking(newRobot); + DetachTracking(context, newRobot); return newRobot!; } throw new DbUpdateException( @@ -223,7 +223,7 @@ await robotQuery robot = await robotQuery.FirstOrDefaultAsync(); ThrowIfRobotIsNull(robot, robotId); NotifySignalROfUpdatedRobot(robot!, robot!.CurrentInstallation!); - DetachTracking(robot); + DetachTracking(context, robot); } public async Task UpdateRobotIsarConnected(string robotId, bool isarConnected) @@ -318,7 +318,7 @@ public async Task Update(Robot robot) robot?.CurrentInstallation, robot != null ? new RobotResponse(robot) : null ); - DetachTracking(robot!); + DetachTracking(context, robot!); } public async Task Delete(string id) @@ -433,7 +433,7 @@ private async Task UpdateRobotProperty( logger.LogError(e, "Failed to update {robotName}", robot.Name); } ; - DetachTracking(robot); + DetachTracking(context, robot); } private async Task ApplyDatabaseUpdate(Installation? installation) @@ -479,15 +479,21 @@ private void NotifySignalROfUpdatedRobot(Robot robot, Installation installation) ); } - public void DetachTracking(Robot robot) + public void DetachTracking(FlotillaDbContext context, Robot robot) { - if (robot.CurrentInstallation != null) - installationService.DetachTracking(robot.CurrentInstallation); - if (robot.CurrentInspectionArea != null) - inspectionAreaService.DetachTracking(robot.CurrentInspectionArea); - if (robot.Model != null) - robotModelService.DetachTracking(robot.Model); context.Entry(robot).State = EntityState.Detached; + if ( + robot.CurrentInstallation != null + && context.Entry(robot.CurrentInstallation).State != EntityState.Detached + ) + installationService.DetachTracking(context, robot.CurrentInstallation); + if ( + robot.CurrentInspectionArea != null + && context.Entry(robot.CurrentInspectionArea).State != EntityState.Detached + ) + inspectionAreaService.DetachTracking(context, robot.CurrentInspectionArea); + if (robot.Model != null && context.Entry(robot.Model).State != EntityState.Detached) + robotModelService.DetachTracking(context, robot.Model); } } } diff --git a/backend/api/Services/SourceService.cs b/backend/api/Services/SourceService.cs index 951b9654..6be6f77b 100644 --- a/backend/api/Services/SourceService.cs +++ b/backend/api/Services/SourceService.cs @@ -27,7 +27,7 @@ public abstract Task CreateSourceIfDoesNotExist( public abstract Task Delete(string id); - public void DetachTracking(Source source); + public void DetachTracking(FlotillaDbContext context, Source source); } [System.Diagnostics.CodeAnalysis.SuppressMessage( @@ -42,7 +42,7 @@ public async Task Create(Source source) { context.Sources.Add(source); await context.SaveChangesAsync(); - DetachTracking(source); + DetachTracking(context, source); return source; } @@ -128,7 +128,7 @@ public async Task CreateSourceIfDoesNotExist( var newSource = await Create(new Source { SourceId = hash, CustomMissionTasks = json }); - DetachTracking(newSource); + DetachTracking(context, newSource); return newSource; } @@ -146,7 +146,7 @@ public async Task CreateSourceIfDoesNotExist( return source; } - public void DetachTracking(Source source) + public void DetachTracking(FlotillaDbContext context, Source source) { context.Entry(source).State = EntityState.Detached; } diff --git a/backend/api/Services/UserInfoServices.cs b/backend/api/Services/UserInfoServices.cs index 77559ea5..8824ad35 100644 --- a/backend/api/Services/UserInfoServices.cs +++ b/backend/api/Services/UserInfoServices.cs @@ -68,7 +68,7 @@ public async Task Update(UserInfo userInfo) public async Task Delete(string id) { - var userInfo = await GetUsersInfo(readOnly: false) + var userInfo = await GetUsersInfo(readOnly: true) .FirstOrDefaultAsync(ev => ev.Id.Equals(id)); if (userInfo is null) { @@ -92,7 +92,7 @@ public async Task Update(UserInfo userInfo) logger.LogWarning("User objectId is null so it will not be added to the database."); return null; } - var userInfo = await ReadByOid(objectId, readOnly: false); + var userInfo = await ReadByOid(objectId, readOnly: true); if (userInfo is null) { var newUserInfo = new UserInfo { Oid = objectId };