feat(templates): phase 1 — derived-template schema (additive)
Phase 1 of the design at
docs/plans/2026-05-12-derive-on-compose-design.md.
Additive schema only — no behavior changes. Existing data and code
paths continue to work; subsequent phases will start writing the
new fields.
Template gains:
IsDerived true when this row was auto-created to back
a composition slot
OwnerCompositionId back-ref to the owning TemplateComposition
(plain int, not an EF nav property — managed
by TemplateService for cascade-delete)
TemplateAttribute / TemplateScript each gain:
IsInherited row copied from base and not yet overridden;
changes to the base flow downward
LockedInDerived on a base, blocks derived from overriding;
enforced at the service layer in later phases
EF Core migration AddDerivedTemplateFields adds four columns:
Templates.IsDerived bit NOT NULL DEFAULT 0
Templates.OwnerCompositionId int NULL
TemplateAttributes.IsInherited bit NOT NULL DEFAULT 0
TemplateAttributes.LockedInDerived bit NOT NULL DEFAULT 0
TemplateScripts.IsInherited bit NOT NULL DEFAULT 0
TemplateScripts.LockedInDerived bit NOT NULL DEFAULT 0
Existing rows get the defaults. Tests across SiteRuntime / TemplateEngine
/ CentralUI suites stay green (129 / 199 / 159).
Next: phase 2 — wire AddCompositionAsync to derive on compose for
new compositions. Old data still flows the direct-reference path
until phase 3's migration script.
This commit is contained in:
1300
src/ScadaLink.ConfigurationDatabase/Migrations/20260512121446_AddDerivedTemplateFields.Designer.cs
generated
Normal file
1300
src/ScadaLink.ConfigurationDatabase/Migrations/20260512121446_AddDerivedTemplateFields.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,83 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace ScadaLink.ConfigurationDatabase.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddDerivedTemplateFields : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsInherited",
|
||||
table: "TemplateScripts",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "LockedInDerived",
|
||||
table: "TemplateScripts",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsDerived",
|
||||
table: "Templates",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "OwnerCompositionId",
|
||||
table: "Templates",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsInherited",
|
||||
table: "TemplateAttributes",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "LockedInDerived",
|
||||
table: "TemplateAttributes",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsInherited",
|
||||
table: "TemplateScripts");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "LockedInDerived",
|
||||
table: "TemplateScripts");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsDerived",
|
||||
table: "Templates");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "OwnerCompositionId",
|
||||
table: "Templates");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsInherited",
|
||||
table: "TemplateAttributes");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "LockedInDerived",
|
||||
table: "TemplateAttributes");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -848,11 +848,17 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
|
||||
b.Property<int?>("FolderId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<bool>("IsDerived")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
.HasColumnType("nvarchar(200)");
|
||||
|
||||
b.Property<int?>("OwnerCompositionId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int?>("ParentTemplateId")
|
||||
.HasColumnType("int");
|
||||
|
||||
@@ -935,9 +941,15 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
|
||||
.HasMaxLength(2000)
|
||||
.HasColumnType("nvarchar(2000)");
|
||||
|
||||
b.Property<bool>("IsInherited")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsLocked")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("LockedInDerived")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(200)
|
||||
@@ -1027,9 +1039,15 @@ namespace ScadaLink.ConfigurationDatabase.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<bool>("IsInherited")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("IsLocked")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<bool>("LockedInDerived")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<TimeSpan?>("MinTimeBetweenRuns")
|
||||
.HasColumnType("time");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user