EF Core, работаю локально, сохраняет/обновляет все дерево данныхC#

Место общения программистов C#
Ответить
Anonymous
 EF Core, работаю локально, сохраняет/обновляет все дерево данных

Сообщение Anonymous »

У меня есть TaskFlowTemplate , довольно стандартный, но немного сложный. Наши пользователи будут иметь возможность работать локально в памяти без необходимости сохранять после каждых изменений. Мой основной ключ - 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 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 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
}
< /code>
Я получаю свои данные, как это, и выполняю сглаженные задачи: < /p>
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);
< /code>
Я изменяю задачи, чтобы быть похожими на модель дерева вместо локально, потому что у меня будет возможность создавать и связывать родительские /дочерние задачи без необходимости сохранять каждый раз. < /p>
public List BuildTaskTree(List 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();
parent.ChildTasks.Add(task);
}
}

// Rotnoder = de utan parent
return flatTasks.Where(t => !t.ParentTaskEntityId.HasValue).ToList();
}

А затем я прохожу каждую активность и устанавливаю их предшественник .
Это работает в памяти, как и должно. Структура данных кажется в порядке при отправке на мой метод обновления. Я ищу и использую модели GPT, но застрял. Я предполагаю, что моя самая большая проблема заключается в том, что ActivityDependency .
Есть ли кто-то, кто может указать мне на правильное направление для обработки такого случая сохранения/обновления?public async Task 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);
< /code>
....
Так что в более простых случаях я загружаю сущность из DB, а затем, как и выше ... а затем Savechanges ... но это не работает здесь ... Я понятия не имею, как я должен идти, чтобы справиться, создавать, обновлять данные в этом дереве. Английский) < /p>
public async Task UpdateTaskFlowTemplate(TaskFlowTemplate updatedTemplate)
{
if (updatedTemplate == null)
throw new ArgumentNullException(nameof(updatedTemplate));

using var db = _dbContextFactory.CreateDbContext();

TaskFlowTemplate existing = null;

if (updatedTemplate.Id != 0)
{
// 10 Retrieve existing template with Tasks + Activities + Suppliers
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 == updatedTemplate.Id);

if (existing == null)
throw new InvalidOperationException($"TaskFlowTemplate with Id {updatedTemplate.Id} not found.");
}

// 20 Update template properties
if (existing != null)
{
db.Entry(existing).CurrentValues.SetValues(updatedTemplate);
}
else
{
existing = updatedTemplate;
db.Add(existing);
}

// 30 Keep track of which Tasks remain (based on Id)
HashSet updatedIds = new HashSet();

// 40 Sync Tasks + Activity + Supplier (without ActivityDependencies)
SyncTasks(existing.Tasks, updatedTemplate.Tasks, db, updatedIds);

// 50 Now we have a complete list of all Tasks that should exist
DeleteMissingTasks(existing.Tasks, updatedIds, db);

// 60 Save Tasks + Activities + Supplier to get Ids for new objects
await db.SaveChangesAsync();

// 70 Handle ActivityDependencies now that all Ids exist
SyncActivityDependencies(existing.Tasks, updatedTemplate.Tasks, db);

// 80 TaskFlowTemplate, set TaskEntity.TaskEntityTemplateId for all Tasks that are templates
foreach (var task in existing.Tasks)
{
if (task.Id != 0)
{
task.TaskEntityTemplateId = task.Id;
task.TaskFlowTemplateId = existing.Id;
task.IsTemplate = true;

db.Entry(task).State = EntityState.Modified;
}
}

// 90 Save ActivityDependencies
await db.SaveChangesAsync();

// Keep only root-level Tasks in TaskFlowTemplate.Tasks
existing.Tasks = existing.Tasks
.Where(t => t.ParentTaskEntityId == null)
.ToList();

return existing;
}


Подробнее здесь: https://stackoverflow.com/questions/797 ... ee-of-data
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»