diff --git a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs index 6447f831..16dc5f21 100644 --- a/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs +++ b/src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Validation/DraftValidator.cs @@ -47,14 +47,17 @@ public static class DraftValidator var signals = draft.Tags .Where(t => t.EquipmentId is not null) .Select(t => (Key: Key(t.EquipmentId!, t.FolderPath, t.Name), Eq: t.EquipmentId!, t.Name)) + // VirtualTag has no FolderPath column today — null is correct here; update if it ever gains one. .Concat(draft.VirtualTags .Select(v => (Key: Key(v.EquipmentId, null, v.Name), Eq: v.EquipmentId, v.Name))); - foreach (var g in signals.GroupBy(s => s.Key, StringComparer.Ordinal).Where(g => g.Count() > 1)) + foreach (var g in signals.GroupBy(s => s.Key, StringComparer.Ordinal)) { - var f = g.First(); + var items = g.ToList(); + if (items.Count <= 1) continue; + var f = items[0]; errors.Add(new("EquipmentSignalNameCollision", - $"{g.Count()} signals collide on OPC UA NodeId '{g.Key}' (equipment '{f.Eq}', name '{f.Name}'); " + + $"{items.Count} signals collide on OPC UA NodeId '{g.Key}' (equipment '{f.Eq}', name '{f.Name}'); " + "a Name must be unique across Tag and VirtualTag within an equipment+folder", f.Eq)); }