using DataModel.Database; using DataModel.Database.Common; using Microsoft.EntityFrameworkCore; namespace Processor; public static class SectionProcessor { /// /// Load one layer of the tree by using the specified depth: /// public static IAsyncEnumerable
LoadLayer(DataContext db, int depth) { return db.Sections.Where(n => n.Depth == depth).OrderBy(n => n.Id).AsAsyncEnumerable(); } /// /// Determine how deep the tree is. /// public static async ValueTask GetDepth(DataContext db) { if(!await db.Sections.AnyAsync()) { return 0; } return await db.Sections.MaxAsync(s => s.Depth); } /// /// Compute the new sections key and its depth, then store the section in the database. /// public static async Task
AddSection(DataContext db, string text, string? parentKey) { // Remove any whitespaces from the section name, regardless of how many e.g. spaces the user typed: var key = string.Join('_', text.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)).ToUpperInvariant(); // Check, if this key already exists: if (await db.Sections.AnyAsync(n => n.DataKey == key)) { var rng = new Random(); while (await db.Sections.AnyAsync(n => n.DataKey == key)) { // Add a random number to the end of the key: key += $"_{rng.Next(1, 10_000)}"; } } // In the case, when the user adds a section to the root, handle the insert differently: if (string.IsNullOrEmpty(parentKey)) { var rootSection = new Section { Depth = 0, DataKey = key, Parent = null, Name = text.Trim(), TextElements = new(), }; db.Sections.Add(rootSection); await db.SaveChangesAsync(); return rootSection; } // Read the parent from the database: var parent = await db.Sections.FirstOrDefaultAsync(n => n.DataKey == parentKey); if (parent is null) throw new ArgumentException($"The section's parent with key {parentKey} does not exist in the database."); // Add the new section to the database: var section = new Section { Name = text.Trim(), DataKey = key, Parent = parent, TextElements = new(), Depth = parent.Depth + 1, }; db.Sections.Add(section); await db.SaveChangesAsync(); return section; } public static async Task RemoveSection(DataContext db, string selectedKey) { // Remove the section from the database: var section2Delete = await db.Sections.FirstOrDefaultAsync(n => n.DataKey == selectedKey); if (section2Delete is null) throw new ArgumentException($"The section with key {selectedKey} does not exist in the database."); // Next, remove all children of the section, and the children's children, etc.: var children = await db.Sections.Where(n => n.Parent == section2Delete).ToListAsync(); foreach (var child in children) await RemoveSection(db, child.DataKey); db.Sections.Remove(section2Delete); await db.SaveChangesAsync(); } public static async Task NumberChildren(DataContext db, string selectedKey) { // Read the section from the database: var section = await db.Sections.FirstOrDefaultAsync(n => n.DataKey == selectedKey); if (section is null) throw new ArgumentException($"The section with key {selectedKey} does not exist in the database."); return await db.Sections.CountAsync(n => n.Parent == section); } }