using Microsoft.EntityFrameworkCore; using ZB.MOM.WW.OtOpcUa.Configuration; using ZB.MOM.WW.OtOpcUa.Configuration.Validation; namespace ZB.MOM.WW.OtOpcUa.Admin.Services; /// /// Runs the managed against a draft's snapshot loaded from the /// Configuration DB. Used by the draft editor's inline validation panel and by the publish /// dialog's pre-check. Structural-only SQL checks live in sp_ValidateDraft; this layer /// owns the content / cross-generation / regex rules. /// public sealed class DraftValidationService(OtOpcUaConfigDbContext db) { public async Task> ValidateAsync(long draftId, CancellationToken ct) { var draft = await db.ConfigGenerations.AsNoTracking() .FirstOrDefaultAsync(g => g.GenerationId == draftId, ct) ?? throw new InvalidOperationException($"Draft {draftId} not found"); var snapshot = new DraftSnapshot { GenerationId = draft.GenerationId, ClusterId = draft.ClusterId, Namespaces = await db.Namespaces.AsNoTracking().Where(n => n.GenerationId == draftId).ToListAsync(ct), DriverInstances = await db.DriverInstances.AsNoTracking().Where(d => d.GenerationId == draftId).ToListAsync(ct), Devices = await db.Devices.AsNoTracking().Where(d => d.GenerationId == draftId).ToListAsync(ct), UnsAreas = await db.UnsAreas.AsNoTracking().Where(a => a.GenerationId == draftId).ToListAsync(ct), UnsLines = await db.UnsLines.AsNoTracking().Where(l => l.GenerationId == draftId).ToListAsync(ct), Equipment = await db.Equipment.AsNoTracking().Where(e => e.GenerationId == draftId).ToListAsync(ct), Tags = await db.Tags.AsNoTracking().Where(t => t.GenerationId == draftId).ToListAsync(ct), PollGroups = await db.PollGroups.AsNoTracking().Where(p => p.GenerationId == draftId).ToListAsync(ct), PriorEquipment = await db.Equipment.AsNoTracking() .Where(e => e.GenerationId != draftId && db.ConfigGenerations.Any(g => g.GenerationId == e.GenerationId && g.ClusterId == draft.ClusterId)) .ToListAsync(ct), ActiveReservations = await db.ExternalIdReservations.AsNoTracking() .Where(r => r.ReleasedAt == null) .ToListAsync(ct), }; return DraftValidator.Validate(snapshot); } }