refactor(configdb): drop GenerationId FK from live-edit entities
Phase 1b of the v2 entity-model rewrite. The design's live-edit model means
the 12 v2 live-edit entities no longer carry a generation scope — they're
edited directly via AdminOperationsActor, with RowVersion (added in Task 14a)
providing last-write-wins detection.
Entity changes (12 files):
Equipment, DriverInstance, Device, Tag, PollGroup, Namespace,
UnsArea, UnsLine, NodeAcl, Script, VirtualTag, ScriptedAlarm
- Removed: public long GenerationId
- Removed: public ConfigGeneration? Generation (navigation)
DbContext changes (OtOpcUaConfigDbContext.cs):
- Removed 12 HasOne(x => x.Generation).WithMany().HasForeignKey... mappings
- Rewrote ~36 indexes: dropped the GenerationId column from each composite
key, renamed UX_<Table>_Generation_<X> -> UX_<Table>_<X> and
IX_<Table>_Generation_<X> -> IX_<Table>_<X>. Logical IDs become globally
unique (UX_<Table>_LogicalId on the LogicalId column alone).
- Removed Namespace's redundant UX_Namespace_Generation_LogicalId_Cluster
index (subsumed by the new UX_Namespace_LogicalId).
Core.Tests fixtures (4 files):
Removed "GenerationId = 1," lines from:
- PermissionTrieBuilderTests.cs (NodeAcl Row factory)
- PermissionTrieTests.cs (NodeAcl Row factory)
- TriePermissionEvaluatorTests.cs (NodeAcl Row factory + 2 gen{1,5}Row
mutations that test stale-generation evaluation; the trie itself still
carries a generation tag via PermissionTrie.GenerationId, fed in via
PermissionTrieBuilder.Build's generationId parameter, so the tests
still exercise the production code path)
- EquipmentNodeWalkerTests.cs (Area/Line/Eq/Tag/VirtualTag/ScriptedAlarm
builders)
Expected breakage (accepted per Task 56 policy):
src/Server/ZB.MOM.WW.OtOpcUa.Server ~25 errors (DriverInstanceBootstrapper,
AuthorizationBootstrap,
EquipmentNamespaceContentLoader,
Phase7Composer, ...)
src/Server/ZB.MOM.WW.OtOpcUa.Admin ~45 errors (VirtualTags.razor,
ScriptedAlarms.razor,
DriverInstanceService,
EquipmentService,
EquipmentImportBatchService,
UnsService,
FocasDriverDetailService,
...)
Server.Tests, Admin.Tests, Admin.E2ETests also break transitively (they
project-reference Server/Admin). All deleted in Task 56.
Verification:
dotnet build src/Core/ZB.MOM.WW.OtOpcUa.Configuration -> 0 errors
dotnet build tests/Core/ZB.MOM.WW.OtOpcUa.Core.Tests -> 0 errors
dotnet build tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests -> 0 errors
dotnet build (whole solution) -> 70 errors, all in Server/Admin
This commit is contained in:
@@ -5,8 +5,6 @@ public sealed class Device
|
||||
{
|
||||
public Guid DeviceRowId { get; set; }
|
||||
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
public required string DeviceId { get; set; }
|
||||
|
||||
/// <summary>Logical FK to <see cref="DriverInstance.DriverInstanceId"/>.</summary>
|
||||
@@ -21,6 +19,4 @@ public sealed class Device
|
||||
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ public sealed class DriverInstance
|
||||
{
|
||||
public Guid DriverInstanceRowId { get; set; }
|
||||
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
public required string DriverInstanceId { get; set; }
|
||||
|
||||
public required string ClusterId { get; set; }
|
||||
@@ -48,6 +46,5 @@ public sealed class DriverInstance
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
public ServerCluster? Cluster { get; set; }
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ public sealed class Equipment
|
||||
{
|
||||
public Guid EquipmentRowId { get; set; }
|
||||
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// System-generated stable internal logical ID. Format: <c>'EQ-' + first 12 hex chars of EquipmentUuid</c>.
|
||||
/// NEVER operator-supplied, NEVER in CSV imports, NEVER editable in Admin UI (decision #125).
|
||||
@@ -62,6 +60,4 @@ public sealed class Equipment
|
||||
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
}
|
||||
|
||||
@@ -10,9 +10,7 @@ public sealed class Namespace
|
||||
{
|
||||
public Guid NamespaceRowId { get; set; }
|
||||
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
/// <summary>Stable logical ID across generations, e.g. "LINE3-OPCUA-equipment".</summary>
|
||||
/// <summary>Stable logical ID, e.g. "LINE3-OPCUA-equipment". Globally unique in v2.</summary>
|
||||
public required string NamespaceId { get; set; }
|
||||
|
||||
public required string ClusterId { get; set; }
|
||||
@@ -29,6 +27,5 @@ public sealed class Namespace
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
public ServerCluster? Cluster { get; set; }
|
||||
}
|
||||
|
||||
@@ -10,8 +10,6 @@ public sealed class NodeAcl
|
||||
{
|
||||
public Guid NodeAclRowId { get; set; }
|
||||
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
public required string NodeAclId { get; set; }
|
||||
|
||||
public required string ClusterId { get; set; }
|
||||
@@ -30,6 +28,4 @@ public sealed class NodeAcl
|
||||
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ public sealed class PollGroup
|
||||
{
|
||||
public Guid PollGroupRowId { get; set; }
|
||||
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
public required string PollGroupId { get; set; }
|
||||
|
||||
public required string DriverInstanceId { get; set; }
|
||||
@@ -17,6 +15,4 @@ public sealed class PollGroup
|
||||
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
}
|
||||
|
||||
@@ -17,9 +17,8 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
||||
public sealed class Script
|
||||
{
|
||||
public Guid ScriptRowId { get; set; }
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
/// <summary>Stable logical id. Carries across generations.</summary>
|
||||
/// <summary>Stable logical id. Globally unique in v2.</summary>
|
||||
public required string ScriptId { get; set; }
|
||||
|
||||
/// <summary>Operator-friendly name for log filtering + Admin UI list view.</summary>
|
||||
@@ -36,6 +35,4 @@ public sealed class Script
|
||||
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
}
|
||||
|
||||
@@ -17,9 +17,8 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
||||
public sealed class ScriptedAlarm
|
||||
{
|
||||
public Guid ScriptedAlarmRowId { get; set; }
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
/// <summary>Stable logical id — drives <c>AlarmConditionType.ConditionName</c>.</summary>
|
||||
/// <summary>Stable logical id — drives <c>AlarmConditionType.ConditionName</c>. Globally unique in v2.</summary>
|
||||
public required string ScriptedAlarmId { get; set; }
|
||||
|
||||
/// <summary>Logical FK to <see cref="Equipment.EquipmentId"/> — owner of this alarm.</summary>
|
||||
@@ -57,6 +56,4 @@ public sealed class ScriptedAlarm
|
||||
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ public sealed class Tag
|
||||
{
|
||||
public Guid TagRowId { get; set; }
|
||||
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
public required string TagId { get; set; }
|
||||
|
||||
public required string DriverInstanceId { get; set; }
|
||||
@@ -45,6 +43,4 @@ public sealed class Tag
|
||||
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ public sealed class UnsArea
|
||||
{
|
||||
public Guid UnsAreaRowId { get; set; }
|
||||
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
public required string UnsAreaId { get; set; }
|
||||
|
||||
public required string ClusterId { get; set; }
|
||||
@@ -19,6 +17,5 @@ public sealed class UnsArea
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
public ServerCluster? Cluster { get; set; }
|
||||
}
|
||||
|
||||
@@ -5,11 +5,9 @@ public sealed class UnsLine
|
||||
{
|
||||
public Guid UnsLineRowId { get; set; }
|
||||
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
public required string UnsLineId { get; set; }
|
||||
|
||||
/// <summary>Logical FK to <see cref="UnsArea.UnsAreaId"/>; resolved within the same generation.</summary>
|
||||
/// <summary>Logical FK to <see cref="UnsArea.UnsAreaId"/>.</summary>
|
||||
public required string UnsAreaId { get; set; }
|
||||
|
||||
/// <summary>UNS level 4 segment: matches <c>^[a-z0-9-]{1,32}$</c> OR equals literal <c>_default</c>.</summary>
|
||||
@@ -19,6 +17,4 @@ public sealed class UnsLine
|
||||
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
}
|
||||
|
||||
@@ -21,9 +21,8 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
||||
public sealed class VirtualTag
|
||||
{
|
||||
public Guid VirtualTagRowId { get; set; }
|
||||
public long GenerationId { get; set; }
|
||||
|
||||
/// <summary>Stable logical id.</summary>
|
||||
/// <summary>Stable logical id. Globally unique in v2.</summary>
|
||||
public required string VirtualTagId { get; set; }
|
||||
|
||||
/// <summary>Logical FK to <see cref="Equipment.EquipmentId"/> — owner of this virtual tag.</summary>
|
||||
@@ -51,6 +50,4 @@ public sealed class VirtualTag
|
||||
|
||||
/// <summary>Optimistic concurrency token for last-write-wins detection in the v2 live-edit model.</summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public ConfigGeneration? Generation { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user