using Microsoft.EntityFrameworkCore; namespace ZB.MOM.WW.OtOpcUa.Configuration.Validation; /// /// Materialises a from the live config DB so /// can run against the current edit state at deploy time. /// /// /// /// This is a whole-DB ("global") snapshot — every cluster's rows in one pass — which is /// what the deploy path needs: the admin-operations actor snapshots and flattens the /// entire config, not one cluster. The validator's rules compare entity-level /// ClusterId fields against each other (e.g. namespace binding), so the snapshot's /// own is not read by any rule and is left empty. /// /// /// is a placeholder (the generation model was /// dropped); no rule reads it. is empty because /// there is no prior-generation table to diff against. /// / are left null so the path-length rule uses its /// conservative upper bound. /// /// public static class DraftSnapshotFactory { /// Builds a from the current config DB rows. /// The config DB context to read from. /// Cancellation token. /// A snapshot populated from the live DB, ready for . public static async Task FromConfigDbAsync(OtOpcUaConfigDbContext db, CancellationToken ct = default) => new DraftSnapshot { GenerationId = 0, // generation model dropped; placeholder (no rule reads it) ClusterId = string.Empty, // global snapshot; rules compare entity ClusterId fields, not this Namespaces = await db.Namespaces.AsNoTracking().ToListAsync(ct), DriverInstances = await db.DriverInstances.AsNoTracking().ToListAsync(ct), Devices = await db.Devices.AsNoTracking().ToListAsync(ct), UnsAreas = await db.UnsAreas.AsNoTracking().ToListAsync(ct), UnsLines = await db.UnsLines.AsNoTracking().ToListAsync(ct), Equipment = await db.Equipment.AsNoTracking().ToListAsync(ct), Tags = await db.Tags.AsNoTracking().ToListAsync(ct), VirtualTags = await db.VirtualTags.AsNoTracking().ToListAsync(ct), PollGroups = await db.PollGroups.AsNoTracking().ToListAsync(ct), PriorEquipment = [], ActiveReservations = await db.ExternalIdReservations .AsNoTracking() .Where(r => r.ReleasedAt == null) // active only — matches DraftSnapshot.ActiveReservations semantics .ToListAsync(ct), }; }