7.3 KiB
7.3 KiB
标签获取时间字段实现方案
1. 需求概述
在 label_replace_requests 表中添加一个新字段 LabelRetrievedAt,用于记录客户获取标签的时间,并通过数据库触发器自动更新该字段。
2. 实现步骤
2.1 修改数据模型
已在 LabelReplaceEntity 类中添加了 LabelRetrievedAt 字段:
/// <summary>
/// 获取标签时间
/// </summary>
[SugarColumn(IsNullable = true)]
public DateTime? LabelRetrievedAt { get; set; }
2.2 数据库表结构更新
方法1:使用代码优先方式
当应用程序启动时,SqlSugar 的 CodeFirst 功能会自动创建新字段。
方法2:手动执行SQL语句
ALTER TABLE label_replace_requests
ADD COLUMN LabelRetrievedAt DATETIME NULL COMMENT '获取标签时间';
2.3 创建触发器
2.3.1 基本触发器
DELIMITER $$
CREATE TRIGGER update_label_retrieved_timestamp
BEFORE UPDATE ON label_replace_requests
FOR EACH ROW
BEGIN
-- 当Label字段被设置或修改时,更新LabelRetrievedAt
IF NEW.Label IS NOT NULL AND (OLD.Label IS NULL OR NEW.Label != OLD.Label) THEN
SET NEW.LabelRetrievedAt = UTC_TIMESTAMP();
END IF;
-- 同时更新UpdatedAt字段
SET NEW.UpdatedAt = UTC_TIMESTAMP();
END$$
DELIMITER ;
2.3.2 包含条件判断的触发器(可选)
DELIMITER $$
CREATE TRIGGER update_label_retrieved_timestamp
BEFORE UPDATE ON label_replace_requests
FOR EACH ROW
BEGIN
-- 当Label字段被设置或修改时,更新LabelRetrievedAt
IF NEW.Label IS NOT NULL AND (OLD.Label IS NULL OR NEW.Label != OLD.Label) THEN
SET NEW.LabelRetrievedAt = UTC_TIMESTAMP();
END IF;
-- 仅当记录确实被修改时才更新UpdatedAt
IF NOT (NEW.BillOfLadingNumber <=> OLD.BillOfLadingNumber AND
NEW.MasterPackageNumber <=> OLD.MasterPackageNumber AND
NEW.ReferenceNumber <=> OLD.ReferenceNumber AND
NEW.NeutralWaybillNumber <=> OLD.NeutralWaybillNumber AND
NEW.FinalMileTrackingNumber <=> OLD.FinalMileTrackingNumber AND
NEW.Label <=> OLD.Label AND
NEW.ReplaceStatus <=> OLD.ReplaceStatus AND
NEW.CustomerId <=> OLD.CustomerId) THEN
SET NEW.UpdatedAt = UTC_TIMESTAMP();
END IF;
END$$
DELIMITER ;
3. 触发器说明
3.1 触发时机
BEFORE UPDATE:在更新操作执行前触发FOR EACH ROW:对每一行更新都会触发
3.2 逻辑说明
- 当
Label字段从NULL变为非NULL,或其值被修改时,更新LabelRetrievedAt为当前时间 - 同时更新
UpdatedAt字段,保持与现有逻辑一致
3.3 时间戳设置
- 使用
UTC_TIMESTAMP()函数获取当前UTC时间,与代码中使用的DateTime.UtcNow保持一致 LabelRetrievedAt字段为可为空的日期时间类型,仅在标签被设置时才更新
4. 测试验证
4.1 功能测试
-
创建测试记录:
INSERT INTO label_replace_requests (NeutralWaybillNumber, ReplaceStatus) VALUES ('TEST123456', 'Y'); -
查询初始状态:
SELECT LabelRetrievedAt, UpdatedAt FROM label_replace_requests WHERE NeutralWaybillNumber = 'TEST123456';预期结果:
LabelRetrievedAt为NULL -
设置标签:
UPDATE label_replace_requests SET Label = 'base64_encoded_pdf' WHERE NeutralWaybillNumber = 'TEST123456'; -
验证时间戳是否更新:
SELECT LabelRetrievedAt, UpdatedAt FROM label_replace_requests WHERE NeutralWaybillNumber = 'TEST123456';预期结果:
LabelRetrievedAt和UpdatedAt都被更新为当前时间 -
更新其他字段:
UPDATE label_replace_requests SET FinalMileTrackingNumber = 'FM123456' WHERE NeutralWaybillNumber = 'TEST123456'; -
验证LabelRetrievedAt是否保持不变:
SELECT LabelRetrievedAt, UpdatedAt FROM label_replace_requests WHERE NeutralWaybillNumber = 'TEST123456';预期结果:
LabelRetrievedAt保持不变,UpdatedAt被更新为当前时间
4.2 性能测试
-
批量更新测试:
-- 创建测试数据 INSERT INTO label_replace_requests (NeutralWaybillNumber, ReplaceStatus) VALUES ('TEST001', 'Y'), ('TEST002', 'Y'), ('TEST003', 'Y'), ('TEST004', 'Y'), ('TEST005', 'Y'); -- 批量更新标签 UPDATE label_replace_requests SET Label = 'base64_encoded_pdf' WHERE NeutralWaybillNumber LIKE 'TEST%'; -
验证批量更新结果:
SELECT NeutralWaybillNumber, LabelRetrievedAt FROM label_replace_requests WHERE NeutralWaybillNumber LIKE 'TEST%';预期结果:所有记录的
LabelRetrievedAt都被更新为当前时间
5. 注意事项
5.1 权限要求
- 需要
CREATE TRIGGER权限 - 需要对
label_replace_requests表有TRIGGER权限 - 需要对
label_replace_requests表有ALTER权限(用于添加新字段)
5.2 性能影响
- 触发器会在每次更新操作时执行,可能影响高频更新场景的性能
- 建议在生产环境中进行性能测试
5.3 维护性
- 触发器逻辑存储在数据库中,与应用代码分离,可能增加维护难度
- 建议在代码中添加注释,说明触发器的存在和功能
5.4 兼容性
- 确保MySQL版本支持触发器(MySQL 5.0及以上版本支持)
- 不同MySQL版本的触发器语法可能略有差异
6. 触发器管理
6.1 修改触发器
-- 先删除旧触发器
DROP TRIGGER IF EXISTS update_label_retrieved_timestamp;
-- 再创建新触发器
DELIMITER $$
CREATE TRIGGER update_label_retrieved_timestamp
BEFORE UPDATE ON label_replace_requests
FOR EACH ROW
BEGIN
-- 当Label字段被设置或修改时,更新LabelRetrievedAt
IF NEW.Label IS NOT NULL AND (OLD.Label IS NULL OR NEW.Label != OLD.Label) THEN
SET NEW.LabelRetrievedAt = UTC_TIMESTAMP();
END IF;
-- 同时更新UpdatedAt字段
SET NEW.UpdatedAt = UTC_TIMESTAMP();
END$$
DELIMITER ;
6.2 删除触发器
DROP TRIGGER IF EXISTS update_label_retrieved_timestamp;
7. 代码优化建议
7.1 数据模型优化
考虑在 LabelReplaceEntity 类中添加构造函数,确保所有时间字段都有合理的默认值:
public LabelReplaceEntity()
{
CreatedAt = DateTime.UtcNow;
UpdatedAt = DateTime.UtcNow;
ReplaceStatus = "Y";
LabelRetrievedAt = null;
}
7.2 服务层优化
在 LabelReplaceService.ProcessLabelReplaceAsync 方法中,当设置或修改标签时,可以考虑在代码层面也设置 LabelRetrievedAt 字段,以确保即使不使用触发器也能正确记录时间:
// 更新现有记录时
if (request.Label != null)
{
existingRecord.Label = request.Label;
existingRecord.LabelRetrievedAt = DateTime.UtcNow;
}
8. 总结
通过添加 LabelRetrievedAt 字段并创建相应的数据库触发器,可以自动记录客户获取标签的时间。这种方法的优点是:
- 自动记录:无需在应用代码中手动设置,触发器会自动处理
- 准确性:仅在标签被设置或修改时才更新时间戳
- 一致性:与现有的
UpdatedAt字段更新逻辑保持一致
在实际应用中,应根据系统的具体情况(如更新频率、性能要求等)选择合适的实现方式。