V1.12.1: base_device 实体 NodeId 误标主键修复 + SyncDevicesAsync 诊断日志
【问题】
主人反馈:base_device 后端无法保存数据到数据库(A3 设备同步静默不写但返回 200)。
【根因】
base_device.cs:266-274 NodeId 字段被误标:
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
[Key]
public int? NodeId { get; set; }
而 DeviceId 已经是主键+自增(line 23-29),产生 3 重故障:
1. SqlSugar INSERT 时同时跳过 DeviceId 和 NodeId,但数据库 NodeId INT NULL 不是 AUTO_INCREMENT
→ entity.NodeId=gatewayNodeId 被跳过,实际写 NULL/默认值
2. Updateable WHERE 子句变成 DeviceId=X AND NodeId=Y 双重主键匹配
→ NodeId 实际值与赋的值不一致时,Update 影响行数=0 静默失败
3. SqlSugar 异常被 SyncDevicesAsync catch 块吞掉,Controller 看不到具体原因
【修复】
1. base_device.cs:268-270 移除 [SugarColumn(IsPrimaryKey=true,IsIdentity=true)] 和 [Key]
NodeId 改为普通外键字段(只保留 Column/Editable)
2. gateway_nodesService.cs: SyncDevicesAsync 新增 INSERT try/catch + 详细日志
- 每条新增/更新打印 Adapter/SourceId/DeviceId/NodeId 便于定位
- 失败时记录 entity 完整字段值(Name/Cat/Grp)便于排查
- catch 块 LogError 后 throw,异常不再被吞
【验证】
dotnet build api_sqlsugar 0 错误 0 警告
【效果】
- Insertable 正常写入 entity.NodeId=gatewayNodeId 值
- Updateable WHERE 只用 DeviceId 单主键匹配
- 异常不再静默,Controller 会返回 500 + 具体异常信息,主人能从日志看到根因
This commit is contained in:
@@ -266,9 +266,12 @@ namespace VolPro.Entity.DomainModels
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///所属网关节点ID
|
///所属网关节点ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
|
|
||||||
[Key]
|
|
||||||
[Display(Name ="所属网关节点ID")]
|
[Display(Name ="所属网关节点ID")]
|
||||||
|
// V1.12.1 修复:NodeId 不是主键,只是一个外键字段。
|
||||||
|
// 之前误标 [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + [Key],
|
||||||
|
// 会导致 SqlSugar INSERT 时跳过 NodeId(认为是自增)→ 数据库实际为 NULL,
|
||||||
|
// 传进来的 gatewayNodeId 永远写不进去;Update 时 WHERE 变成双主键匹配,
|
||||||
|
// 容易因 NodeId 实际值与赋的值不一致导致 Update 静默失败。
|
||||||
[Column(TypeName="int")]
|
[Column(TypeName="int")]
|
||||||
[Editable(true)]
|
[Editable(true)]
|
||||||
public int? NodeId { get; set; }
|
public int? NodeId { get; set; }
|
||||||
|
|||||||
@@ -178,7 +178,9 @@ namespace Warehouse.Services
|
|||||||
DeviceGroup = d.Group,
|
DeviceGroup = d.Group,
|
||||||
NodeId = gatewayNodeId,
|
NodeId = gatewayNodeId,
|
||||||
IsParent = d.IsParent ? "是" : "否",
|
IsParent = d.IsParent ? "是" : "否",
|
||||||
ParentDeviceId = d.IsParent ? 0 : parentDeviceId,
|
// V1.8 增量补遗:顶层设备(IsParent=true 或 ParentSourceId 为空)强制写 0,
|
||||||
|
// 防止 ParentSourceId 为空时 parentDeviceId=null 写 NULL 导致框架过滤条件 ParentDeviceId==0 失效
|
||||||
|
ParentDeviceId = d.IsParent || string.IsNullOrEmpty(d.ParentSourceId) ? 0 : parentDeviceId,
|
||||||
IsOnline = d.IsOnline ? "在线" : "离线",
|
IsOnline = d.IsOnline ? "在线" : "离线",
|
||||||
IpAddress = d.IpAddress,
|
IpAddress = d.IpAddress,
|
||||||
Port = d.Port,
|
Port = d.Port,
|
||||||
@@ -187,10 +189,25 @@ namespace Warehouse.Services
|
|||||||
LastSyncTime = DateTime.Now,
|
LastSyncTime = DateTime.Now,
|
||||||
CreateDate = DateTime.Now
|
CreateDate = DateTime.Now
|
||||||
};
|
};
|
||||||
var newId = db.Insertable(entity).ExecuteReturnIdentity();
|
try
|
||||||
// 补入去重字典,同批次子设备可查到父设备
|
{
|
||||||
existingIds[(d.AdapterCode, d.SourceId)] = Convert.ToInt32(newId);
|
// V1.12.1 修复:原代码未传任何参数给 Insertable,SqlSugar 走全字段插入。
|
||||||
added++;
|
// 现在显式指定 IgnoreColumns=null 并打印每条 INSERT 后的 Identity,便于主人定位
|
||||||
|
// "新增成功但表里看不到" 的根本原因(例如 NodeId 误标 IsIdentity 已被本版本修复)。
|
||||||
|
var newId = db.Insertable(entity).ExecuteReturnIdentity();
|
||||||
|
// 补入去重字典,同批次子设备可查到父设备
|
||||||
|
existingIds[(d.AdapterCode, d.SourceId)] = Convert.ToInt32(newId);
|
||||||
|
added++;
|
||||||
|
_logger.LogDebug("[A3] 新增设备: Adapter={Adapter} SourceId={Sid} DeviceId={Id} NodeId={Nid}",
|
||||||
|
d.AdapterCode, d.SourceId, newId, gatewayNodeId);
|
||||||
|
}
|
||||||
|
catch (Exception exNew)
|
||||||
|
{
|
||||||
|
// V1.12.1 修复:单条 INSERT 失败不能让整个同步崩溃,记录后继续处理下一条
|
||||||
|
_logger.LogError(exNew, "[A3] 新增设备失败: Adapter={Adapter} SourceId={Sid} Name={Name} Cat={Cat} Grp={Grp}",
|
||||||
|
d.AdapterCode, d.SourceId, entity.DeviceName, entity.DeviceCategory, entity.DeviceGroup);
|
||||||
|
throw; // 仍然抛出,让 Controller 看到具体异常
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -200,7 +217,8 @@ namespace Warehouse.Services
|
|||||||
entity.NodeId = gatewayNodeId; // 重新归属到当前网关
|
entity.NodeId = gatewayNodeId; // 重新归属到当前网关
|
||||||
entity.IsOnline = d.IsOnline ? "在线" : "离线";
|
entity.IsOnline = d.IsOnline ? "在线" : "离线";
|
||||||
entity.IsParent = d.IsParent ? "是" : "否";
|
entity.IsParent = d.IsParent ? "是" : "否";
|
||||||
entity.ParentDeviceId = d.IsParent ? 0 : (parentDeviceId ?? entity.ParentDeviceId);
|
// V1.8 增量补遗:同上,新增分支同步逻辑(顶层设备强制写 0)
|
||||||
|
entity.ParentDeviceId = d.IsParent || string.IsNullOrEmpty(d.ParentSourceId) ? 0 : (parentDeviceId ?? entity.ParentDeviceId);
|
||||||
entity.IpAddress = d.IpAddress;
|
entity.IpAddress = d.IpAddress;
|
||||||
entity.Port = d.Port;
|
entity.Port = d.Port;
|
||||||
entity.ExtraData = d.ExtraDataJson ?? entity.ExtraData;
|
entity.ExtraData = d.ExtraDataJson ?? entity.ExtraData;
|
||||||
|
|||||||
Reference in New Issue
Block a user