diff --git a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs
index e14b495e..35913425 100644
--- a/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs
+++ b/src/Server/ZB.MOM.WW.OtOpcUa.AdminUI/Uns/UnsTreeService.cs
@@ -9,9 +9,9 @@ namespace ZB.MOM.WW.OtOpcUa.AdminUI.Uns;
/// rows to the pure to nest into the browse tree.
///
///
-/// A new context is created per call via the pooled factory — the same pattern every
-/// AdminUI page uses — so the service is safe to register as a scoped singleton and call
-/// concurrently from independent Blazor circuits.
+/// Each call creates and disposes its own context via the pooled factory — the same pattern
+/// every AdminUI page uses — so the service is safe to register as Scoped and used per
+/// Blazor circuit.
///
public sealed class UnsTreeService(IDbContextFactory dbFactory) : IUnsTreeService
{
@@ -55,11 +55,12 @@ public sealed class UnsTreeService(IDbContextFactory dbF
.ToListAsync(ct))
.ToDictionary(x => x.EquipmentId, x => x.Count, StringComparer.Ordinal);
- // Per-equipment virtual-tag counts (EquipmentId is always set on virtual tags).
+ // Per-equipment virtual-tag counts (virtual tags with no equipment are excluded).
var vtagCounts = (await db.VirtualTags
.AsNoTracking()
+ .Where(v => v.EquipmentId != null)
.GroupBy(v => v.EquipmentId)
- .Select(g => new { EquipmentId = g.Key, Count = g.Count() })
+ .Select(g => new { EquipmentId = g.Key!, Count = g.Count() })
.ToListAsync(ct))
.ToDictionary(x => x.EquipmentId, x => x.Count, StringComparer.Ordinal);