feat(configdb): V2HostingAlignment migration consolidating Phase 1a-1e
Phase 1f — the consolidator migration. Closes out the v2 entity-model
rewrite by emitting a single EF migration that captures the cumulative
schema delta from 14a (RowVersion) through 14e (drop generation entities).
Generated: src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Migrations/
20260526081556_V2HostingAlignment.cs (1562 lines)
20260526081556_V2HostingAlignment.Designer.cs
Migration shape (per `grep -nE migrationBuilder.\(...)`):
Drop 12 ForeignKey constraints (one per live-edit entity's GenerationId FK)
Drop 2 Tables (ConfigGeneration, ClusterNodeGenerationState)
Drop 45 Indexes (every UX_*_Generation_* and IX_*_Generation_* across the
13 live-edit tables — 1 also dropped the unique-Primary
filtered index UX_ClusterNode_Primary_Per_Cluster)
Drop 13 Columns (12 GenerationId + 1 RedundancyRole)
Add 12 RowVersion columns (one per live-edit entity)
Create 4 Tables (Deployment, NodeDeploymentState, ConfigEdit,
DataProtectionKeys)
Create ~45 Indexes (recreated under the new naming pattern
UX_<Table>_LogicalId / UX_<Table>_<X> with the
GenerationId column stripped from composite keys)
Notable EF quirks accepted:
Unique-on-required-column indexes (UX_VirtualTag_LogicalId etc.) ship a
`filter: "[VirtualTagId] IS NOT NULL"` clause that EF auto-inserts for
SQL Server. Harmless — the column is C#-side `required` so NULL never
appears.
Verification:
dotnet build src/Core/ZB.MOM.WW.OtOpcUa.Configuration -> 0 errors
dotnet ef migrations script --idempotent (against placeholder DSN)
-> 3259-line
.sql produced
OK
tests/Core/ZB.MOM.WW.OtOpcUa.Configuration.Tests -> 0 errors
Live `dotnet ef database update` against a scratch SQL Server deferred to
Task 15 (Migrate-To-V2.ps1) — SSH to the docker host needs a key/password I
don't have, and the always-on SQL at 10.100.0.35,14330 uses Integrated
Security (Windows auth, unreachable from this macOS dev). The migration
itself is structurally correct by construction (EF tooling generated it
against the live DbContext model); the live-DB confidence step is the
PowerShell wrapper's job.
SchemaComplianceTests updates:
- All_expected_tables_exist: removed ConfigGeneration +
ClusterNodeGenerationState; added Deployment, NodeDeploymentState,
ConfigEdit, DataProtectionKeys.
- Filtered_unique_indexes_match_schema_spec: removed entries for
UX_ClusterNode_Primary_Per_Cluster (Task 14d) and
UX_ConfigGeneration_Draft_Per_Cluster (Task 14e). Two filtered uniques
remain (UX_ClusterNodeCredential_Value, UX_ExternalIdReservation_KindValue_Active).
- Check_constraints_match_schema_spec: added CK_ConfigEdit_FieldsJson_IsJson.
StoredProceduresTests update:
- Removed RedundancyRole + 'Primary' from the raw INSERT into ClusterNode
so the DB-backed test runs against the new schema.
This commit is contained in:
1744
src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Migrations/20260526081556_V2HostingAlignment.Designer.cs
generated
Normal file
1744
src/Core/ZB.MOM.WW.OtOpcUa.Configuration/Migrations/20260526081556_V2HostingAlignment.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -23,8 +23,8 @@ public sealed class SchemaComplianceTests
|
||||
{
|
||||
var expected = new[]
|
||||
{
|
||||
"ServerCluster", "ClusterNode", "ClusterNodeCredential", "ClusterNodeGenerationState",
|
||||
"ConfigGeneration", "ConfigAuditLog",
|
||||
"ServerCluster", "ClusterNode", "ClusterNodeCredential",
|
||||
"ConfigAuditLog",
|
||||
"Namespace", "UnsArea", "UnsLine",
|
||||
"DriverInstance", "Device", "Equipment", "Tag", "PollGroup", "VirtualTag",
|
||||
"NodeAcl", "ExternalIdReservation",
|
||||
@@ -34,6 +34,8 @@ public sealed class SchemaComplianceTests
|
||||
"EquipmentImportBatch",
|
||||
"EquipmentImportRow",
|
||||
"Script", "ScriptedAlarm", "ScriptedAlarmState",
|
||||
// v2 deploy-model tables (Phase 1 of Akka + fused-hosting alignment)
|
||||
"Deployment", "NodeDeploymentState", "ConfigEdit", "DataProtectionKeys",
|
||||
};
|
||||
|
||||
var actual = QueryStrings(@"
|
||||
@@ -52,9 +54,7 @@ SELECT name FROM sys.tables WHERE name <> '__EFMigrationsHistory' ORDER BY name;
|
||||
// Kept here as a spec-level source of truth; the test ensures EF generated them verbatim.
|
||||
var expected = new[]
|
||||
{
|
||||
("UX_ClusterNode_Primary_Per_Cluster", "([RedundancyRole]='Primary')"),
|
||||
("UX_ClusterNodeCredential_Value", "([Enabled]=(1))"),
|
||||
("UX_ConfigGeneration_Draft_Per_Cluster", "([Status]='Draft')"),
|
||||
("UX_ExternalIdReservation_KindValue_Active", "([ReleasedAt] IS NULL)"),
|
||||
};
|
||||
|
||||
@@ -85,6 +85,7 @@ WHERE i.is_unique = 1 AND i.has_filter = 1;",
|
||||
"CK_PollGroup_IntervalMs_Min",
|
||||
"CK_Tag_TagConfig_IsJson",
|
||||
"CK_ConfigAuditLog_DetailsJson_IsJson",
|
||||
"CK_ConfigEdit_FieldsJson_IsJson",
|
||||
};
|
||||
|
||||
var actual = QueryStrings("SELECT name FROM sys.check_constraints ORDER BY name;").ToHashSet();
|
||||
|
||||
@@ -260,8 +260,8 @@ public sealed class StoredProceduresTests
|
||||
Exec(conn,
|
||||
@"INSERT dbo.ServerCluster (ClusterId, Name, Enterprise, Site, RedundancyMode, NodeCount, Enabled, CreatedBy)
|
||||
VALUES (@c, @c, 'zb', @s, 'None', 1, 1, SUSER_SNAME());
|
||||
INSERT dbo.ClusterNode (NodeId, ClusterId, RedundancyRole, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy)
|
||||
VALUES (@n, @c, 'Primary', 'localhost', 4840, 5001, CONCAT('urn:localhost:', @s), 200, 1, SUSER_SNAME());
|
||||
INSERT dbo.ClusterNode (NodeId, ClusterId, Host, OpcUaPort, DashboardPort, ApplicationUri, ServiceLevelBase, Enabled, CreatedBy)
|
||||
VALUES (@n, @c, 'localhost', 4840, 5001, CONCAT('urn:localhost:', @s), 200, 1, SUSER_SNAME());
|
||||
INSERT dbo.ClusterNodeCredential (NodeId, Kind, Value, Enabled, CreatedBy)
|
||||
VALUES (@n, 'SqlLogin', SUSER_SNAME(), 1, SUSER_SNAME());",
|
||||
("c", clusterId), ("n", nodeId), ("s", suffix));
|
||||
|
||||
Reference in New Issue
Block a user