Files
DMS/DMS.Application/Services/Processors/ValueConvertProcessor.cs
David P.G d6bb606b0e 本次提交包含了两个主要部分:一个关键的数据库并发问题修复,以及一个关于历史记录功能的增强。
1. 数据库并发修复 (Bug Fix):
   2. 历史记录功能增强 (Feature):
  `
  fix(db): 修复数据库并发连接问题并增强历史记录功能
  `

  正文:

  `
  本次提交主要包含一个关键的 Bug 修复和一项功能增强。

  1.  修复数据库并发问题:
      *   重构 SqlSugarDbContext,使其作为 SqlSugarClient 的工厂。
      *   GetInstance() 方法现在每次调用都会返回一个新的客户端实例,解决了因单例客户端导致的多线程并发访问 MySqlConnection 的问题。

  2.  增强历史记录功能:
      *   为 VariableHistory 相关的模型、DTO 和实体添加了 NumericValue 属性,以便在历史记录中同时存储数值和字符串值。
      *   更新了 HistoryProcessor 以保存 NumericValue。
      *   对 ValueConvertProcessor 的逻辑进行了重构,以更好地支持值转换流程。
2025-10-03 00:05:17 +08:00

127 lines
4.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Data;
using System.Globalization;
using DMS.Application.DTOs;
using DMS.Application.Interfaces;
using DMS.Application.Models;
using DMS.Core.Enums;
using Microsoft.Extensions.Logging;
namespace DMS.Application.Services.Processors;
public class ValueConvertProcessor : IVariableProcessor
{
private readonly ILogger<ValueConvertProcessor> _logger;
public ValueConvertProcessor(ILogger<ValueConvertProcessor> logger)
{
_logger = logger;
}
public Task ProcessAsync(VariableContext context)
{
var oldValue = context.Data.DataValue;
// 如果值没有变化则中断处理链
if (context.Data.DataValue == context.NewValue)
{
context.IsHandled = true;
}
// 步骤 1: 将原始值转换为 DataValue 和 NumericValue
context.Data.DataValue = context.NewValue;
if (context.Data.DataType == DataType.Bool)
{
context.Data.NumericValue=context.NewValue=="True"?1:0;
context.Data.DisplayValue = context.NewValue;
}
else
{
if (double.TryParse(context.Data.DataValue, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsedFromStr))
{
context.Data.NumericValue = parsedFromStr;
}
// 步骤 2: 根据公式计算 DisplayValue
CalculateDisplayValue(context.Data);
}
context.Data.UpdatedAt = DateTime.Now;
return Task.CompletedTask;
}
/// <summary>
/// 根据转换公式计算用于UI显示的DisplayValue
/// </summary>
/// <param name="variable">需要处理的变量DTO</param>
private void CalculateDisplayValue(VariableDto variable)
{
// 默认情况下,显示值等于原始数据值
variable.DisplayValue = variable.DataValue;
// 如果没有转换公式,则直接返回
if (string.IsNullOrWhiteSpace(variable.ConversionFormula))
{
return;
}
try
{
// 将公式中的 'x' 替换为实际的数值
// 使用 InvariantCulture 确保小数点是 '.'
string expression = variable.ConversionFormula.ToLowerInvariant()
.Replace("x", variable.NumericValue.ToString(CultureInfo.InvariantCulture));
// 使用 DataTable.Compute 来安全地计算表达式
var result = new DataTable().Compute(expression, null);
// 将计算结果格式化后赋给 DisplayValue
if (result is double || result is decimal || result is float)
{
variable.DisplayValue = string.Format("{0:F2}", result); // 默认格式化为两位小数,可根据需要调整
variable.NumericValue = Convert.ToDouble(result); // 更新NumericValue为计算后的值
}
else
{
variable.DisplayValue = result.ToString();
// 尝试将字符串结果解析回double以更新NumericValue
if (double.TryParse(result.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture, out var parsedResult))
{
variable.NumericValue = parsedResult;
}
} }
catch (Exception ex)
{
_logger.LogError(ex, $"为变量 {variable.Name} (ID: {variable.Id}) 计算DisplayValue时出错。公式: '{variable.ConversionFormula}'");
// 如果计算出错DisplayValue 将保持为原始的 DataValue保证程序健壮性
}
}
/// <summary>
/// 将从 S7 读取的对象值转换为字符串表示和数值表示
/// </summary>
/// <param name="variable">关联的变量 DTO</param>
/// <param name="value">从 S7 读取的原始对象值</param>
private void ConvertS7ValueToStringAndNumeric(VariableDto variable, string value)
{
if (value == null)
return;
string directConversion = null;
double numericValue = 0.0;
if (variable.DataType == DataType.Bool)
{
numericValue=value.ToString()=="True"?1.0:0.0;
directConversion = value.ToString();
return;
}
variable.DataValue = directConversion ?? value.ToString() ?? string.Empty;
variable.NumericValue = numericValue;
}
}