diff --git a/EgwCoreLib.Lux.Data/Repository/Catalog/TemplateRepository.cs b/EgwCoreLib.Lux.Data/Repository/Catalog/TemplateRepository.cs index 008a3f1e..39d004ec 100644 --- a/EgwCoreLib.Lux.Data/Repository/Catalog/TemplateRepository.cs +++ b/EgwCoreLib.Lux.Data/Repository/Catalog/TemplateRepository.cs @@ -32,65 +32,81 @@ namespace EgwCoreLib.Lux.Data.Repository.Utils public async Task CloneAsync(TemplateModel rec2clone) { await using var dbCtx = await CreateContextAsync(); - DateTime now = DateTime.Now; - // 1. Recupero il record originale con i child - var currRec = await dbCtx.DbSetTemplate - .Include(x => x.TemplateRowNav) - .FirstOrDefaultAsync(x => x.TemplateID == rec2clone.TemplateID); - - if (currRec == null) - return false; - - // 2. Creo il nuovo parent - var newRec = new TemplateModel + // Wrap in transaction for atomicity + await using var tx = dbCtx.Database.BeginTransaction(); + try { - Name = rec2clone.Name, - Envir = rec2clone.Envir, - Description = rec2clone.Description, - SourceType = rec2clone.SourceType, - }; + DateTime now = DateTime.Now; - // 3. Clono i child - newRec.TemplateRowNav = currRec.TemplateRowNav - .Select(c => new TemplateRowModel + // 1. Recupero il record originale con i child + var currRec = await dbCtx.DbSetTemplate + .Include(x => x.TemplateRowNav) + .FirstOrDefaultAsync(x => x.TemplateID == rec2clone.TemplateID); + + if (currRec == null) { - AwaitBom = c.AwaitBom, - AwaitPrice = c.AwaitPrice, - BomCost = c.BomCost, - BomOk = c.BomOk, - BomPrice = c.BomPrice, - Envir = c.Envir, - FileName = c.FileName, - FileResource = c.FileResource, - FileSize = c.FileSize, - Inserted = now, - ItemBOM = c.ItemBOM, - ItemJCD = c.ItemJCD, - ItemOk = c.ItemOk, - ItemSteps = c.ItemSteps, - ItemTags = c.ItemTags, - JobID = c.JobID, - Note = c.Note, - ProdItemQty = c.ProdItemQty, - Qty = c.Qty, - RowNum = c.RowNum, - SellingItemID = c.SellingItemID, - SerStruct = c.SerStruct, - StepCost = c.StepCost, - StepFlowTime = c.StepFlowTime, - StepLeadTime = c.StepLeadTime, - StepPrice = c.StepPrice, - Name = c.Name, - TemplateRowUID = c.TemplateRowDtx - }) - .ToList(); + tx.Rollback(); + return false; + } - // 4. Aggiungo il nuovo parent (EF aggiunge anche i child) - dbCtx.DbSetTemplate.Add(newRec); + // 2. Creo il nuovo parent + var newRec = new TemplateModel + { + Name = rec2clone.Name, + Envir = rec2clone.Envir, + Description = rec2clone.Description, + SourceType = rec2clone.SourceType, + }; - // 5. Salvo tutto - return await dbCtx.SaveChangesAsync() > 0; + // 3. Clono i child + newRec.TemplateRowNav = currRec.TemplateRowNav + .Select(c => new TemplateRowModel + { + AwaitBom = c.AwaitBom, + AwaitPrice = c.AwaitPrice, + BomCost = c.BomCost, + BomOk = c.BomOk, + BomPrice = c.BomPrice, + Envir = c.Envir, + FileName = c.FileName, + FileResource = c.FileResource, + FileSize = c.FileSize, + Inserted = now, + ItemBOM = c.ItemBOM, + ItemJCD = c.ItemJCD, + ItemOk = c.ItemOk, + ItemSteps = c.ItemSteps, + ItemTags = c.ItemTags, + JobID = c.JobID, + Note = c.Note, + ProdItemQty = c.ProdItemQty, + Qty = c.Qty, + RowNum = c.RowNum, + SellingItemID = c.SellingItemID, + SerStruct = c.SerStruct, + StepCost = c.StepCost, + StepFlowTime = c.StepFlowTime, + StepLeadTime = c.StepLeadTime, + StepPrice = c.StepPrice, + Name = c.Name, + TemplateRowUID = c.TemplateRowDtx + }) + .ToList(); + + // 4. Aggiungo il nuovo parent (EF aggiunge anche i child) + dbCtx.DbSetTemplate.Add(newRec); + + // 5. Salvo tutto in transazione + bool done = await dbCtx.SaveChangesAsync() > 0; + tx.Commit(); + return done; + } + catch + { + tx.Rollback(); + throw; + } } public async Task CountChildrenAsync(int TemplateID) @@ -145,10 +161,23 @@ namespace EgwCoreLib.Lux.Data.Repository.Utils public async Task SaveRowsAsync(List rows) { await using var dbCtx = await CreateContextAsync(); - foreach (var row in rows) - dbCtx.Entry(row).State = EntityState.Modified; - return await dbCtx.SaveChangesAsync() > 0; + // Wrap in transaction for atomicity when saving multiple rows + await using var tx = dbCtx.Database.BeginTransaction(); + try + { + foreach (var row in rows) + dbCtx.Entry(row).State = EntityState.Modified; + + bool done = await dbCtx.SaveChangesAsync() > 0; + tx.Commit(); + return done; + } + catch + { + tx.Rollback(); + throw; + } } public async Task UpdateAsync(TemplateModel entity) diff --git a/EgwCoreLib.Lux.Data/Repository/Catalog/TemplateRowRepository.cs b/EgwCoreLib.Lux.Data/Repository/Catalog/TemplateRowRepository.cs index 94b7ad8e..b6ea44ae 100644 --- a/EgwCoreLib.Lux.Data/Repository/Catalog/TemplateRowRepository.cs +++ b/EgwCoreLib.Lux.Data/Repository/Catalog/TemplateRowRepository.cs @@ -30,57 +30,73 @@ namespace EgwCoreLib.Lux.Data.Repository.Utils public async Task CloneAsync(TemplateRowModel rec2clone) { await using var dbCtx = await CreateContextAsync(); - var currRec = await dbCtx.DbSetTemplateRow - .FirstOrDefaultAsync(x => x.TemplateRowID == rec2clone.TemplateRowID); - if (currRec == null) - return false; - - // cerco ultimo rec... - var lastRec = await dbCtx - .DbSetTemplateRow - .Where(x => x.TemplateID == rec2clone.TemplateID) - .OrderByDescending(x => x.RowNum) - .FirstOrDefaultAsync(); - int rowNum = lastRec != null ? lastRec.RowNum + 1 : 1; - - var newRec = new TemplateRowModel() + // Wrap in transaction for atomicity + await using var tx = dbCtx.Database.BeginTransaction(); + try { - Name = rec2clone.Name, - Envir = rec2clone.Envir, - AwaitBom = rec2clone.AwaitBom, - AwaitPrice = rec2clone.AwaitPrice, - BomCost = rec2clone.BomCost, - BomOk = rec2clone.BomOk, - BomPrice = rec2clone.BomPrice, - FileName = rec2clone.FileName, - FileResource = rec2clone.FileResource, - FileSize = rec2clone.FileSize, - Inserted = rec2clone.Inserted, - ItemBOM = rec2clone.ItemBOM, - ItemJCD = rec2clone.ItemJCD, - ItemOk = rec2clone.ItemOk, - ItemSteps = rec2clone.ItemSteps, - ItemTags = rec2clone.ItemTags, - JobID = rec2clone.JobID, - Note = rec2clone.Note, - ProdItemQty = rec2clone.ProdItemQty, - Qty = rec2clone.Qty, - RowNum = rowNum, - SellingItemID = rec2clone.SellingItemID, - SellingItemNav = rec2clone.SellingItemNav, - SerStruct = rec2clone.SerStruct, - StepCost = rec2clone.StepCost, - StepFlowTime = rec2clone.StepFlowTime, - StepLeadTime = rec2clone.StepLeadTime, - StepPrice = rec2clone.StepPrice, - TemplateID = rec2clone.TemplateID, - TemplateRowUID = rec2clone.TemplateRowDtx - }; + var currRec = await dbCtx.DbSetTemplateRow + .FirstOrDefaultAsync(x => x.TemplateRowID == rec2clone.TemplateRowID); - dbCtx.DbSetTemplateRow.Add(newRec); + if (currRec == null) + { + tx.Rollback(); + return false; + } - return await dbCtx.SaveChangesAsync() > 0; + // cerco ultimo rec... + var lastRec = await dbCtx + .DbSetTemplateRow + .Where(x => x.TemplateID == rec2clone.TemplateID) + .OrderByDescending(x => x.RowNum) + .FirstOrDefaultAsync(); + int rowNum = lastRec != null ? lastRec.RowNum + 1 : 1; + + var newRec = new TemplateRowModel() + { + Name = rec2clone.Name, + Envir = rec2clone.Envir, + AwaitBom = rec2clone.AwaitBom, + AwaitPrice = rec2clone.AwaitPrice, + BomCost = rec2clone.BomCost, + BomOk = rec2clone.BomOk, + BomPrice = rec2clone.BomPrice, + FileName = rec2clone.FileName, + FileResource = rec2clone.FileResource, + FileSize = rec2clone.FileSize, + Inserted = rec2clone.Inserted, + ItemBOM = rec2clone.ItemBOM, + ItemJCD = rec2clone.ItemJCD, + ItemOk = rec2clone.ItemOk, + ItemSteps = rec2clone.ItemSteps, + ItemTags = rec2clone.ItemTags, + JobID = rec2clone.JobID, + Note = rec2clone.Note, + ProdItemQty = rec2clone.ProdItemQty, + Qty = rec2clone.Qty, + RowNum = rowNum, + SellingItemID = rec2clone.SellingItemID, + SellingItemNav = rec2clone.SellingItemNav, + SerStruct = rec2clone.SerStruct, + StepCost = rec2clone.StepCost, + StepFlowTime = rec2clone.StepFlowTime, + StepLeadTime = rec2clone.StepLeadTime, + StepPrice = rec2clone.StepPrice, + TemplateID = rec2clone.TemplateID, + TemplateRowUID = rec2clone.TemplateRowDtx + }; + + dbCtx.DbSetTemplateRow.Add(newRec); + + bool done = await dbCtx.SaveChangesAsync() > 0; + tx.Commit(); + return done; + } + catch + { + tx.Rollback(); + throw; + } } public async Task DeleteAsync(TemplateRowModel entity) @@ -118,10 +134,23 @@ namespace EgwCoreLib.Lux.Data.Repository.Utils public async Task SaveRowsAsync(List rows) { await using var dbCtx = await CreateContextAsync(); - foreach (var row in rows) - dbCtx.Entry(row).State = EntityState.Modified; - return await dbCtx.SaveChangesAsync() > 0; + // Wrap in transaction for atomicity when saving multiple rows + await using var tx = dbCtx.Database.BeginTransaction(); + try + { + foreach (var row in rows) + dbCtx.Entry(row).State = EntityState.Modified; + + bool done = await dbCtx.SaveChangesAsync() > 0; + tx.Commit(); + return done; + } + catch + { + tx.Rollback(); + throw; + } } public async Task UpdateAsync(TemplateRowModel entity)