feat(config): forward-only migration deleting orphaned SystemPlatform namespace data (clean break)
This commit is contained in:
+1758
File diff suppressed because it is too large
Load Diff
+120
@@ -0,0 +1,120 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace ZB.MOM.WW.OtOpcUa.Configuration.Migrations
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Forward-only DATA-cleanup migration for the Galaxy clean break: the
|
||||||
|
/// <c>NamespaceKind.SystemPlatform</c> enum member was removed (Galaxy is now an
|
||||||
|
/// Equipment-kind driver). <c>Namespace.Kind</c> is persisted as a string via
|
||||||
|
/// <c>HasConversion<string></c>, so any leftover row with <c>Kind = 'SystemPlatform'</c>
|
||||||
|
/// would throw at materialisation time (no matching enum member) the moment the new code
|
||||||
|
/// reads the table. This deletes those namespaces plus everything that hung off them.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// There is NO schema/model change in this migration — the model snapshot is unchanged.
|
||||||
|
/// The unique index <c>UX_Namespace_Cluster_Kind</c> (unique on <c>ClusterId, Kind</c>) is
|
||||||
|
/// intentionally KEPT: <c>Simulated</c> remains a reserved kind, so one-of-each-kind-per-cluster
|
||||||
|
/// is still the correct constraint.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The cross-table relationships in this graph are LOGICAL foreign keys (string Id columns,
|
||||||
|
/// e.g. <c>DriverInstance.NamespaceId</c> → <c>Namespace.NamespaceId</c>,
|
||||||
|
/// <c>Tag.DriverInstanceId</c> → <c>DriverInstance.DriverInstanceId</c>) enforced by
|
||||||
|
/// <c>sp_ValidateDraft</c>, NOT physical DB FK constraints — only the <c>*.ClusterId</c>
|
||||||
|
/// relationships are real DB FKs. So no FK constraint can be violated here. The deletes are
|
||||||
|
/// nonetheless ordered child→parent so no orphaned rows are left behind, and every statement
|
||||||
|
/// is keyed off the set of SystemPlatform namespaces, so on a DB with zero such rows every
|
||||||
|
/// DELETE simply affects 0 rows (idempotent / safe to run repeatedly).
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class CleanupSystemPlatformNamespaces : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// Delete in child -> parent order. Everything is keyed off the set of namespaces whose
|
||||||
|
// Kind = 'SystemPlatform' (the string form persisted by HasConversion<string>), funnelled
|
||||||
|
// through the DriverInstances that lived in those namespaces.
|
||||||
|
migrationBuilder.Sql(@"
|
||||||
|
-- Defensive: SystemPlatform namespaces historically held only EquipmentId-NULL mirror tags, but a
|
||||||
|
-- stray equipment-scoped tag / Equipment could be bound to a SystemPlatform-namespace driver. Clean
|
||||||
|
-- both, plus anything that FKs into the affected Equipment (VirtualTag / ScriptedAlarm / state).
|
||||||
|
|
||||||
|
-- Grandchildren of the affected Equipment ------------------------------------------------
|
||||||
|
-- ScriptedAlarmState is keyed by ScriptedAlarm.ScriptedAlarmId; remove before its ScriptedAlarm.
|
||||||
|
DELETE FROM [ScriptedAlarmState]
|
||||||
|
WHERE [ScriptedAlarmId] IN (
|
||||||
|
SELECT [ScriptedAlarmId] FROM [ScriptedAlarm]
|
||||||
|
WHERE [EquipmentId] IN (
|
||||||
|
SELECT [EquipmentId] FROM [Equipment]
|
||||||
|
WHERE [DriverInstanceId] IN (
|
||||||
|
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||||
|
WHERE [NamespaceId] IN (
|
||||||
|
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform'))));
|
||||||
|
|
||||||
|
DELETE FROM [ScriptedAlarm]
|
||||||
|
WHERE [EquipmentId] IN (
|
||||||
|
SELECT [EquipmentId] FROM [Equipment]
|
||||||
|
WHERE [DriverInstanceId] IN (
|
||||||
|
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||||
|
WHERE [NamespaceId] IN (
|
||||||
|
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform')));
|
||||||
|
|
||||||
|
DELETE FROM [VirtualTag]
|
||||||
|
WHERE [EquipmentId] IN (
|
||||||
|
SELECT [EquipmentId] FROM [Equipment]
|
||||||
|
WHERE [DriverInstanceId] IN (
|
||||||
|
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||||
|
WHERE [NamespaceId] IN (
|
||||||
|
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform')));
|
||||||
|
|
||||||
|
-- Children of the affected DriverInstances ------------------------------------------------
|
||||||
|
-- Tags bound to those drivers: both EquipmentId-NULL mirror tags AND any equipment-scoped tag.
|
||||||
|
DELETE FROM [Tag]
|
||||||
|
WHERE [DriverInstanceId] IN (
|
||||||
|
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||||
|
WHERE [NamespaceId] IN (
|
||||||
|
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform'));
|
||||||
|
|
||||||
|
DELETE FROM [PollGroup]
|
||||||
|
WHERE [DriverInstanceId] IN (
|
||||||
|
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||||
|
WHERE [NamespaceId] IN (
|
||||||
|
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform'));
|
||||||
|
|
||||||
|
DELETE FROM [Device]
|
||||||
|
WHERE [DriverInstanceId] IN (
|
||||||
|
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||||
|
WHERE [NamespaceId] IN (
|
||||||
|
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform'));
|
||||||
|
|
||||||
|
DELETE FROM [Equipment]
|
||||||
|
WHERE [DriverInstanceId] IN (
|
||||||
|
SELECT [DriverInstanceId] FROM [DriverInstance]
|
||||||
|
WHERE [NamespaceId] IN (
|
||||||
|
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform'));
|
||||||
|
|
||||||
|
-- The DriverInstances themselves ----------------------------------------------------------
|
||||||
|
DELETE FROM [DriverInstance]
|
||||||
|
WHERE [NamespaceId] IN (
|
||||||
|
SELECT [NamespaceId] FROM [Namespace] WHERE [Kind] = 'SystemPlatform');
|
||||||
|
|
||||||
|
-- The SystemPlatform namespaces (the rows that would crash EF on read) --------------------
|
||||||
|
DELETE FROM [Namespace] WHERE [Kind] = 'SystemPlatform';
|
||||||
|
");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
// Forward-only data cleanup: the deleted SystemPlatform namespaces and their dependent
|
||||||
|
// rows cannot be reconstructed (the data is gone, and SystemPlatform is no longer a valid
|
||||||
|
// NamespaceKind). Intentionally a no-op rather than a throw, so rolling back a LATER
|
||||||
|
// migration does not blow up on this one.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user