I have a TaskFlowTemplate, pretty standard but a bit complex. Our users will have the ability to work locally in memory without need to save after every changes. My primary key is int Id.
public class TaskFlowTemplate { public int Id { get; set; } // This is found on every class [NotMapped] public Guid Guid { get; set; } = Guid.NewGuid(); // Maybe need this to link som data in memory before we got Id from DB, this one is on every one // ... public ICollection<TaskEntity> Tasks { get; set; }}public class TaskEntity{ ....... // one-to-one relation if TaskEntity is an activity public int? ActivityEntityId { get; set; } public ActivityEntity Activity { get; set; }}public class ActivityEntity{ .... public ICollection<ActivityDependency> Dependencies { get; set; } public TaskEntity Task { get; set; } // Backref.}public class ActivityDependency{ ... public int ActivityId { get; set; } public ActivityEntity Activity { get; set; } public int PredecessorId { get; set; } public ActivityEntity Predecessor { get; set; } [NotMapped] public Guid PredecessorGuid { get; set; } // use when link in memory}I get my data like this and get tasks flattened:
using var db = _dbContextFactory.CreateDbContext();return await db.TaskFlowTemplates .Include(t => t.Tasks) .ThenInclude(te => te.Activity) .ThenInclude(a => a.Dependencies) .Include(t => t.Tasks) .ThenInclude(te => te.Supplier) .FirstOrDefaultAsync(t => t.Id == id);I change tasks to be like a tree model instead locally because I will have ability to create and link parent / child tasks without the need to save every time.
public List<TaskEntity> BuildTaskTree(List<TaskEntity> flatTasks){ // Indexera alla tasks på Id (eller Guid om du kör med det internt) var taskLookup = flatTasks.ToDictionary(t => t.Id); foreach (var task in flatTasks) { if (task.ParentTaskEntityId.HasValue && taskLookup.TryGetValue(task.ParentTaskEntityId.Value, out var parent)) { parent.ChildTasks ??= new List<TaskEntity>(); parent.ChildTasks.Add(task); } } // Rotnoder = de utan parent return flatTasks.Where(t => !t.ParentTaskEntityId.HasValue).ToList();}And then I go through every ActivityDependency and set their PredecessorGuid.
This works in memory as it should. Data structure seems ok when sending to my update method.
Now I have problems when I will save/update changes. I've search and use GPT models but I got stuck. I guess my biggest problem are on the ActivityDependency.
Is there someone that could point me on right direction for handle an save/update case like this?
------ EDIT
I use db factory so when I work with data locally it's detached..
public async Task<TaskFlowTemplate> UpdateTaskFlowTemplate(TaskFlowTemplate taskFlowTemplate){using var db = _dbContextFactory.CreateDbContext(); var existing = await db.TaskFlowTemplates .Include(t => t.Tasks) .ThenInclude(te => te.Activity) .ThenInclude(a => a.Dependencies) .Include(t => t.Tasks) .ThenInclude(te => te.Supplier) .FirstOrDefaultAsync(t => t.Id == taskFlowTemplate.Id);db.Entry(existing).CurrentValues.SetValues(taskFlowTemplate);....
so in simplier case I load entity from db, and then like above... and then SaveChanges... But that doesn't work here... I don't have a clue how I should go on to handle create, remove, update data in this tree.