fix(configdb): make ResyncLdapGroupMappingSeed migration idempotent (guarded insert) (#70)
This commit is contained in:
+42
-4
@@ -7,18 +7,56 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Migrations
|
||||
/// <inheritdoc />
|
||||
public partial class ResyncLdapGroupMappingSeed : Migration
|
||||
{
|
||||
/// <summary>
|
||||
/// SQLite idempotent insert for the Id=5 (SCADA-Viewers → Viewer) seed row.
|
||||
/// <c>INSERT OR IGNORE</c> skips the row when the <c>Id</c> primary key already
|
||||
/// exists, so replaying this migration against a DB that already carries Id=5
|
||||
/// (e.g. one seeded by a newer HasData baseline) is a no-op rather than a PK
|
||||
/// violation. Exposed as a constant so the idempotency test can exercise the
|
||||
/// exact SQL the migration emits on the SQLite branch.
|
||||
/// </summary>
|
||||
internal const string SqliteInsertSql =
|
||||
"INSERT OR IGNORE INTO \"LdapGroupMappings\" (\"Id\", \"LdapGroupName\", \"Role\") " +
|
||||
"VALUES (5, 'SCADA-Viewers', 'Viewer');";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.InsertData(
|
||||
table: "LdapGroupMappings",
|
||||
columns: new[] { "Id", "LdapGroupName", "Role" },
|
||||
values: new object[] { 5, "SCADA-Viewers", "Viewer" });
|
||||
// #70: this seed insert must be idempotent. The original unconditional
|
||||
// InsertData threw a PK violation (and crash-looped startup, since dev
|
||||
// auto-applies migrations) on any pre-existing DB that already had Id=5
|
||||
// — e.g. one seeded via the old HasData baseline. Guard the insert so it
|
||||
// is a no-op when the row already exists. Provider-aware because the
|
||||
// production central DB is SQL Server while dev/test run on SQLite, and
|
||||
// the two speak different conditional-insert dialects (mirrors the
|
||||
// NotificationOutboxRepository.InsertIfNotExists pattern, #286).
|
||||
if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite")
|
||||
{
|
||||
// SQLite: INSERT OR IGNORE silently skips the row on a PK clash.
|
||||
migrationBuilder.Sql(SqliteInsertSql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// SQL Server: guard with IF NOT EXISTS. LdapGroupMappings.Id is an
|
||||
// IDENTITY column (InitialSchema declares SqlServer:Identity "1, 1"),
|
||||
// so an explicit Id value requires SET IDENTITY_INSERT ON/OFF around
|
||||
// the INSERT — exactly what EF's InsertData emitted for this row.
|
||||
migrationBuilder.Sql(@"
|
||||
IF NOT EXISTS (SELECT 1 FROM [LdapGroupMappings] WHERE [Id] = 5)
|
||||
BEGIN
|
||||
SET IDENTITY_INSERT [LdapGroupMappings] ON;
|
||||
INSERT INTO [LdapGroupMappings] ([Id], [LdapGroupName], [Role])
|
||||
VALUES (5, N'SCADA-Viewers', N'Viewer');
|
||||
SET IDENTITY_INSERT [LdapGroupMappings] OFF;
|
||||
END");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// Idempotent delete: removes the Id=5 row if present, no-op otherwise.
|
||||
// Unchanged in behaviour from the original DeleteData.
|
||||
migrationBuilder.DeleteData(
|
||||
table: "LdapGroupMappings",
|
||||
keyColumn: "Id",
|
||||
|
||||
Reference in New Issue
Block a user