diff --git a/EgwCoreLib.Lux.Data/Repository/Job/JobStepRepository.cs b/EgwCoreLib.Lux.Data/Repository/Job/JobStepRepository.cs index 5c14f6b6..a25edd7e 100644 --- a/EgwCoreLib.Lux.Data/Repository/Job/JobStepRepository.cs +++ b/EgwCoreLib.Lux.Data/Repository/Job/JobStepRepository.cs @@ -26,25 +26,40 @@ namespace EgwCoreLib.Lux.Data.Repository.Job { await using var dbCtx = await CreateContextAsync(); - var dbResult = await dbCtx.DbSetJobStep - .FirstOrDefaultAsync(x => x.JobStepID == rec2del.JobStepID); - - if (dbResult == null) - return false; - - var list2Move = await dbCtx.DbSetJobStep - .Where(x => x.JobID == rec2del.JobID && x.Index > dbResult.Index) - .ToListAsync(); - - foreach (var item in list2Move) + // Wrap in transaction for atomicity (multi-row update + delete) + await using var tx = dbCtx.Database.BeginTransaction(); + try { - item.Index--; - dbCtx.Entry(item).State = EntityState.Modified; + var dbResult = await dbCtx.DbSetJobStep + .FirstOrDefaultAsync(x => x.JobStepID == rec2del.JobStepID); + + if (dbResult == null) + return false; + + var list2Move = await dbCtx.DbSetJobStep + .Where(x => x.JobID == rec2del.JobID && x.Index > dbResult.Index) + .ToListAsync(); + + foreach (var item in list2Move) + { + item.Index--; + dbCtx.Entry(item).State = EntityState.Modified; + } + + dbCtx.DbSetJobStep.Remove(dbResult); + + bool done = await dbCtx.SaveChangesAsync() > 0; + + if (done) + tx.Commit(); + + return done; + } + catch + { + tx.Rollback(); + throw; } - - dbCtx.DbSetJobStep.Remove(dbResult); - - return await dbCtx.SaveChangesAsync() > 0; } public async Task GetByIdAsync(int recId) @@ -70,34 +85,50 @@ namespace EgwCoreLib.Lux.Data.Repository.Job public async Task MoveAsync(JobStepModel selRec, bool moveUp) { await using var dbCtx = await CreateContextAsync(); - var currRec = await dbCtx.DbSetJobStep - .FirstOrDefaultAsync(x => x.JobStepID == selRec.JobStepID); - if (currRec == null) - return false; + // Wrap in transaction for atomicity (multi-row update) + await using var tx = dbCtx.Database.BeginTransaction(); + try + { + var currRec = await dbCtx.DbSetJobStep + .FirstOrDefaultAsync(x => x.JobStepID == selRec.JobStepID); - int numRec = await dbCtx.DbSetJobStep - .CountAsync(x => x.JobID == selRec.JobID); + if (currRec == null) + return false; - int newPos = moveUp ? currRec.Index - 1 : currRec.Index + 1; + int numRec = await dbCtx.DbSetJobStep + .CountAsync(x => x.JobID == selRec.JobID); - bool canMove = moveUp ? newPos > 0 : newPos <= numRec; - if (!canMove) - return false; + int newPos = moveUp ? currRec.Index - 1 : currRec.Index + 1; - var otherRec = await dbCtx.DbSetJobStep - .FirstOrDefaultAsync(x => x.JobID == selRec.JobID && x.Index == newPos); + bool canMove = moveUp ? newPos > 0 : newPos <= numRec; + if (!canMove) + return false; - if (otherRec == null) - return false; + var otherRec = await dbCtx.DbSetJobStep + .FirstOrDefaultAsync(x => x.JobID == selRec.JobID && x.Index == newPos); - otherRec.Index = currRec.Index; - currRec.Index = newPos; + if (otherRec == null) + return false; - dbCtx.Entry(otherRec).State = EntityState.Modified; - dbCtx.Entry(currRec).State = EntityState.Modified; + otherRec.Index = currRec.Index; + currRec.Index = newPos; - return await dbCtx.SaveChangesAsync() > 0; + dbCtx.Entry(otherRec).State = EntityState.Modified; + dbCtx.Entry(currRec).State = EntityState.Modified; + + bool done = await dbCtx.SaveChangesAsync() > 0; + + if (done) + tx.Commit(); + + return done; + } + catch + { + tx.Rollback(); + throw; + } } public async Task UpdateAsync(JobStepModel entity) diff --git a/EgwCoreLib.Lux.Data/Repository/Job/JobTaskRepository.cs b/EgwCoreLib.Lux.Data/Repository/Job/JobTaskRepository.cs index 6400d28b..ba522535 100644 --- a/EgwCoreLib.Lux.Data/Repository/Job/JobTaskRepository.cs +++ b/EgwCoreLib.Lux.Data/Repository/Job/JobTaskRepository.cs @@ -26,25 +26,40 @@ namespace EgwCoreLib.Lux.Data.Repository.Job { await using var dbCtx = await CreateContextAsync(); - var dbResult = await dbCtx.DbSetJobTask - .FirstOrDefaultAsync(x => x.JobID == rec2del.JobID); - - if (dbResult == null) - return false; - - var list2Move = await dbCtx.DbSetJobTask - .Where(x => x.JobID == rec2del.JobID && x.Index > dbResult.Index) - .ToListAsync(); - - foreach (var item in list2Move) + // Wrap in transaction for atomicity (multi-row update + delete) + await using var tx = dbCtx.Database.BeginTransaction(); + try { - item.Index--; - dbCtx.Entry(item).State = EntityState.Modified; + var dbResult = await dbCtx.DbSetJobTask + .FirstOrDefaultAsync(x => x.JobID == rec2del.JobID); + + if (dbResult == null) + return false; + + var list2Move = await dbCtx.DbSetJobTask + .Where(x => x.JobID == rec2del.JobID && x.Index > dbResult.Index) + .ToListAsync(); + + foreach (var item in list2Move) + { + item.Index--; + dbCtx.Entry(item).State = EntityState.Modified; + } + + dbCtx.DbSetJobTask.Remove(dbResult); + + bool done = await dbCtx.SaveChangesAsync() > 0; + + if (done) + tx.Commit(); + + return done; + } + catch + { + tx.Rollback(); + throw; } - - dbCtx.DbSetJobTask.Remove(dbResult); - - return await dbCtx.SaveChangesAsync() > 0; } public async Task> GetAllAsync() @@ -66,73 +81,105 @@ namespace EgwCoreLib.Lux.Data.Repository.Job public async Task MergeTagsAsync(int JobID, List reqTagList) { await using var dbCtx = await CreateContextAsync(); - var currRec = await dbCtx.DbSetJobTask - .Where(x => x.JobID == JobID) - .Include(t => t.TagNav) - .FirstOrDefaultAsync(); - if (currRec == null) - return false; - - var currentTags = currRec.TagNav.Select(t => t.CodTag).ToList(); - - // calcolo modifiche - var toAdd = reqTagList.Except(currentTags).ToList(); - var toRemove = currentTags.Except(reqTagList).ToList(); - - // aggiunte - foreach (var tag in toAdd) + // Wrap in transaction for atomicity (multi-row add + multi-row remove) + await using var tx = dbCtx.Database.BeginTransaction(); + try { - currRec.TagNav.Add(new JobTaskTagModel + var currRec = await dbCtx.DbSetJobTask + .Where(x => x.JobID == JobID) + .Include(t => t.TagNav) + .FirstOrDefaultAsync(); + + if (currRec == null) + return false; + + var currentTags = currRec.TagNav.Select(t => t.CodTag).ToList(); + + // calcolo modifiche + var toAdd = reqTagList.Except(currentTags).ToList(); + var toRemove = currentTags.Except(reqTagList).ToList(); + + // aggiunte + foreach (var tag in toAdd) { - JobID = JobID, - CodTag = tag - }); + currRec.TagNav.Add(new JobTaskTagModel + { + JobID = JobID, + CodTag = tag + }); + } + // rimozioni + foreach (var tag in toRemove) + { + var entity = currRec.TagNav.FirstOrDefault(t => t.CodTag == tag); + if (entity != null) + dbCtx.Remove(entity); + } + + dbCtx.Entry(currRec).State = EntityState.Modified; + + bool done = await dbCtx.SaveChangesAsync() > 0; + + if (done) + tx.Commit(); + + return done; } - // rimozioni - foreach (var tag in toRemove) + catch { - var entity = currRec.TagNav.FirstOrDefault(t => t.CodTag == tag); - if (entity != null) - dbCtx.Remove(entity); + tx.Rollback(); + throw; } - - dbCtx.Entry(currRec).State = EntityState.Modified; - - return await dbCtx.SaveChangesAsync() > 0; } public async Task MoveAsync(JobTaskModel selRec, bool moveUp) { await using var dbCtx = await CreateContextAsync(); - var currRec = await dbCtx.DbSetJobTask - .FirstOrDefaultAsync(x => x.JobID == selRec.JobID); - if (currRec == null) - return false; + // Wrap in transaction for atomicity (multi-row update) + await using var tx = dbCtx.Database.BeginTransaction(); + try + { + var currRec = await dbCtx.DbSetJobTask + .FirstOrDefaultAsync(x => x.JobID == selRec.JobID); - int numRec = await dbCtx.DbSetJobTask - .CountAsync(); + if (currRec == null) + return false; - int newPos = moveUp ? currRec.Index - 1 : currRec.Index + 1; + int numRec = await dbCtx.DbSetJobTask + .CountAsync(); - bool canMove = moveUp ? newPos > 0 : newPos <= numRec; - if (!canMove) - return false; + int newPos = moveUp ? currRec.Index - 1 : currRec.Index + 1; - var otherRec = await dbCtx.DbSetJobTask - .FirstOrDefaultAsync(x => x.Index == newPos); + bool canMove = moveUp ? newPos > 0 : newPos <= numRec; + if (!canMove) + return false; - if (otherRec == null) - return false; + var otherRec = await dbCtx.DbSetJobTask + .FirstOrDefaultAsync(x => x.Index == newPos); - otherRec.Index = currRec.Index; - currRec.Index = newPos; + if (otherRec == null) + return false; - dbCtx.Entry(otherRec).State = EntityState.Modified; - dbCtx.Entry(currRec).State = EntityState.Modified; + otherRec.Index = currRec.Index; + currRec.Index = newPos; - return await dbCtx.SaveChangesAsync() > 0; + dbCtx.Entry(otherRec).State = EntityState.Modified; + dbCtx.Entry(currRec).State = EntityState.Modified; + + bool done = await dbCtx.SaveChangesAsync() > 0; + + if (done) + tx.Commit(); + + return done; + } + catch + { + tx.Rollback(); + throw; + } } public async Task UpdateAsync(JobTaskModel entity)