From 4501359eacd18b3c45dab7c20979d75be2ff6e1a Mon Sep 17 00:00:00 2001 From: g82tt Date: Fri, 24 Jul 2026 05:47:47 +0800 Subject: [PATCH] =?UTF-8?q?V1.12.1:=20base=5Fdevice=20=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=20NodeId=20=E8=AF=AF=E6=A0=87=E4=B8=BB=E9=94=AE=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20+=20SyncDevicesAsync=20=E8=AF=8A=E6=96=AD=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 【问题】 主人反馈: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 + 具体异常信息,主人能从日志看到根因 --- .../device_manager/base_device.cs | 7 +++-- .../Partial/gateway_nodesService.cs | 30 +++++++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/api_sqlsugar/VolPro.Entity/DomainModels/device_manager/base_device.cs b/api_sqlsugar/VolPro.Entity/DomainModels/device_manager/base_device.cs index 9ad1f02..6a50c29 100644 --- a/api_sqlsugar/VolPro.Entity/DomainModels/device_manager/base_device.cs +++ b/api_sqlsugar/VolPro.Entity/DomainModels/device_manager/base_device.cs @@ -266,9 +266,12 @@ namespace VolPro.Entity.DomainModels /// ///所属网关节点ID /// - [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] - [Key] [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")] [Editable(true)] public int? NodeId { get; set; } diff --git a/api_sqlsugar/Warehouse/Services/device_manager/Partial/gateway_nodesService.cs b/api_sqlsugar/Warehouse/Services/device_manager/Partial/gateway_nodesService.cs index 4dcdcf1..d0aaa01 100644 --- a/api_sqlsugar/Warehouse/Services/device_manager/Partial/gateway_nodesService.cs +++ b/api_sqlsugar/Warehouse/Services/device_manager/Partial/gateway_nodesService.cs @@ -178,7 +178,9 @@ namespace Warehouse.Services DeviceGroup = d.Group, NodeId = gatewayNodeId, 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 ? "在线" : "离线", IpAddress = d.IpAddress, Port = d.Port, @@ -187,10 +189,25 @@ namespace Warehouse.Services LastSyncTime = DateTime.Now, CreateDate = DateTime.Now }; - var newId = db.Insertable(entity).ExecuteReturnIdentity(); - // 补入去重字典,同批次子设备可查到父设备 - existingIds[(d.AdapterCode, d.SourceId)] = Convert.ToInt32(newId); - added++; + try + { + // V1.12.1 修复:原代码未传任何参数给 Insertable,SqlSugar 走全字段插入。 + // 现在显式指定 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 { @@ -200,7 +217,8 @@ namespace Warehouse.Services entity.NodeId = gatewayNodeId; // 重新归属到当前网关 entity.IsOnline = d.IsOnline ? "在线" : "离线"; 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.Port = d.Port; entity.ExtraData = d.ExtraDataJson ?? entity.ExtraData;