using EgwCoreLib.Lux.Data.DbModel.Job; using Microsoft.EntityFrameworkCore; namespace EgwCoreLib.Lux.Data.Repository.Job { public class JobStepRepository : BaseRepository, IJobStepRepository { #region Public Constructors public JobStepRepository(IDbContextFactory ctxFactory) : base(ctxFactory) { } #endregion Public Constructors #region Public Methods public async Task AddAsync(JobStepModel entity) { await using var dbCtx = await CreateContextAsync(); await dbCtx.DbSetJobStep.AddAsync(entity); return await dbCtx.SaveChangesAsync() > 0; } public async Task DeleteAsync(JobStepModel rec2del) { // Add validation for null entity if (rec2del == null) return false; await using var dbCtx = await CreateContextAsync(); // Wrap in transaction for atomicity (multi-row update + delete) await using var tx = await dbCtx.Database.BeginTransactionAsync(); try { 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; } } public async Task GetByIdAsync(int recId) { await using var dbCtx = await CreateContextAsync(); return await dbCtx.DbSetJobStep.FirstOrDefaultAsync(x => x.JobStepID == recId); } public async Task> GetByParentAsync(int jobID) { await using var dbCtx = await CreateContextAsync(); return await dbCtx.DbSetJobStep .Where(x => x.JobID == jobID) .Include(c => c.JobNav) .Include(c => c.PhaseNav) .Include(c => c.ResourceNav) .Include(c => c.TagNav) .Include(c => c.ResourceNav.DriverNav) .AsNoTracking() .ToListAsync(); } public async Task MoveAsync(JobStepModel selRec, bool moveUp) { // Add validation for null entity if (selRec == null) return false; await using var dbCtx = await CreateContextAsync(); // Wrap in transaction for atomicity (multi-row update) await using var tx = await dbCtx.Database.BeginTransactionAsync(); try { var currRec = await dbCtx.DbSetJobStep .FirstOrDefaultAsync(x => x.JobStepID == selRec.JobStepID); if (currRec == null) return false; int numRec = await dbCtx.DbSetJobStep .CountAsync(x => x.JobID == selRec.JobID); int newPos = moveUp ? currRec.Index - 1 : currRec.Index + 1; bool canMove = moveUp ? newPos > 0 : newPos <= numRec; if (!canMove) return false; var otherRec = await dbCtx.DbSetJobStep .FirstOrDefaultAsync(x => x.JobID == selRec.JobID && x.Index == newPos); if (otherRec == null) return false; otherRec.Index = currRec.Index; currRec.Index = newPos; 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) { await using var dbCtx = await CreateContextAsync(); var trackedEntity = await dbCtx.DbSetJobStep.FirstOrDefaultAsync(x => x.JobStepID == entity.JobStepID); if (trackedEntity != null) { dbCtx.Entry(trackedEntity).CurrentValues.SetValues(entity); } else { dbCtx.DbSetJobStep.Update(entity); } return await dbCtx.SaveChangesAsync() > 0; } #endregion Public Methods } }