feat(config): make Equipment.DriverInstanceId nullable + driver-less AdminUI support + migration

This commit is contained in:
Joseph Doherty
2026-06-08 06:49:28 -04:00
parent a94d03a194
commit d2dbf7b0d7
8 changed files with 1823 additions and 9 deletions
@@ -19,8 +19,11 @@ public sealed class Equipment
/// <summary>UUIDv4, IMMUTABLE across all generations of the same EquipmentId. Downstream-consumer join key.</summary>
public Guid EquipmentUuid { get; set; }
/// <summary>Logical FK to the driver providing data for this equipment.</summary>
public required string DriverInstanceId { get; set; }
/// <summary>
/// Optional logical FK to the driver providing data for this equipment.
/// <c>null</c> = VirtualTag-only / driver-less equipment (no field driver).
/// </summary>
public string? DriverInstanceId { get; set; }
/// <summary>Optional logical FK to a multi-device driver's device.</summary>
public string? DeviceId { get; set; }
@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ZB.MOM.WW.OtOpcUa.Configuration.Migrations
{
/// <inheritdoc />
public partial class NullableEquipmentDriverInstanceId : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "DriverInstanceId",
table: "Equipment",
type: "nvarchar(64)",
maxLength: 64,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(64)",
oldMaxLength: 64);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "DriverInstanceId",
table: "Equipment",
type: "nvarchar(64)",
maxLength: 64,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(64)",
oldMaxLength: 64,
oldNullable: true);
}
}
}
@@ -546,7 +546,6 @@ namespace ZB.MOM.WW.OtOpcUa.Configuration.Migrations
.HasColumnType("nvarchar(512)");
b.Property<string>("DriverInstanceId")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
@@ -72,7 +72,7 @@ else
<div class="col-md-6 mb-3">
<label class="form-label" for="driver">Driver instance</label>
<InputSelect id="driver" @bind-Value="_form.DriverInstanceId" class="form-select form-select-sm">
<option value="">— pick a driver</option>
<option value="">(none / driver-less)</option>
@foreach (var d in _drivers)
{
<option value="@d.DriverInstanceId">@d.DriverInstanceId &mdash; @d.Name (@d.DriverType)</option>
@@ -206,7 +206,6 @@ else
try
{
if (string.IsNullOrEmpty(_form.UnsLineId)) { _error = "Pick a UNS line."; return; }
if (string.IsNullOrEmpty(_form.DriverInstanceId)) { _error = "Pick a driver instance."; return; }
await using var db = await DbFactory.CreateDbContextAsync();
if (IsNew)
@@ -219,7 +218,7 @@ else
{
EquipmentId = equipmentId,
EquipmentUuid = uuid,
DriverInstanceId = _form.DriverInstanceId,
DriverInstanceId = string.IsNullOrWhiteSpace(_form.DriverInstanceId) ? null : _form.DriverInstanceId,
UnsLineId = _form.UnsLineId,
Name = _form.Name,
MachineCode = _form.MachineCode,
@@ -242,7 +241,7 @@ else
var entity = await db.Equipment.FirstOrDefaultAsync(e => e.EquipmentId == EquipmentId);
if (entity is null) { _error = "Row no longer exists."; return; }
db.Entry(entity).Property(e => e.RowVersion).OriginalValue = _form.RowVersion;
entity.DriverInstanceId = _form.DriverInstanceId;
entity.DriverInstanceId = string.IsNullOrWhiteSpace(_form.DriverInstanceId) ? null : _form.DriverInstanceId;
entity.UnsLineId = _form.UnsLineId;
entity.Name = _form.Name;
entity.MachineCode = _form.MachineCode;
@@ -292,7 +291,7 @@ else
public string Name { get; set; } = "";
[Required] public string MachineCode { get; set; } = "";
[Required] public string UnsLineId { get; set; } = "";
[Required] public string DriverInstanceId { get; set; } = "";
public string? DriverInstanceId { get; set; }
public string? ZTag { get; set; }
public string? SAPID { get; set; }
public string? Manufacturer { get; set; }
@@ -188,7 +188,7 @@ else
d => nsById.TryGetValue(d.NamespaceId, out var ns) ? ns : namespaces.First());
var driverIds = _drivers.Select(d => d.DriverInstanceId).ToHashSet();
_equipment = await db.Equipment.AsNoTracking()
.Where(e => driverIds.Contains(e.DriverInstanceId))
.Where(e => e.DriverInstanceId != null && driverIds.Contains(e.DriverInstanceId))
.OrderBy(e => e.MachineCode)
.ToListAsync();