本次提交包含了两个主要部分:一个关键的数据库并发问题修复,以及一个关于历史记录功能的增强。

1. 数据库并发修复 (Bug Fix):
   2. 历史记录功能增强 (Feature):
  `
  fix(db): 修复数据库并发连接问题并增强历史记录功能
  `

  正文:

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

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

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

View File

@@ -11,5 +11,6 @@ public class VariableHistoryDto
public int VariableId { get; set; } public int VariableId { get; set; }
public string VariableName { get; set; } public string VariableName { get; set; }
public string Value { get; set; } public string Value { get; set; }
public double NumericValue { get; set; }
public DateTime Timestamp { get; set; } public DateTime Timestamp { get; set; }
} }

View File

@@ -42,6 +42,7 @@ public class HistoryProcessor : IVariableProcessor, IDisposable
{ {
VariableId = context.Data.Id, VariableId = context.Data.Id,
Value = context.Data.DisplayValue?.ToString() ?? string.Empty, Value = context.Data.DisplayValue?.ToString() ?? string.Empty,
NumericValue = context.Data.NumericValue,
Timestamp = DateTime.Now // 记录当前时间 Timestamp = DateTime.Now // 记录当前时间
}; };

View File

@@ -3,6 +3,7 @@ using System.Globalization;
using DMS.Application.DTOs; using DMS.Application.DTOs;
using DMS.Application.Interfaces; using DMS.Application.Interfaces;
using DMS.Application.Models; using DMS.Application.Models;
using DMS.Core.Enums;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace DMS.Application.Services.Processors; namespace DMS.Application.Services.Processors;
@@ -19,21 +20,37 @@ public class ValueConvertProcessor : IVariableProcessor
public Task ProcessAsync(VariableContext context) public Task ProcessAsync(VariableContext context)
{ {
var oldValue = context.Data.DataValue; var oldValue = context.Data.DataValue;
// 步骤 1: 将原始值转换为 DataValue 和 NumericValue
ConvertS7ValueToStringAndNumeric(context.Data, context.NewValue);
// 步骤 2: 根据公式计算 DisplayValue
CalculateDisplayValue(context.Data);
context.Data.UpdatedAt = DateTime.Now;
// 如果值没有变化则中断处理链 // 如果值没有变化则中断处理链
if (context.Data.DataValue == oldValue) if (context.Data.DataValue == context.NewValue)
{ {
context.IsHandled = true; 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; return Task.CompletedTask;
} }
@@ -89,77 +106,21 @@ public class ValueConvertProcessor : IVariableProcessor
/// </summary> /// </summary>
/// <param name="variable">关联的变量 DTO</param> /// <param name="variable">关联的变量 DTO</param>
/// <param name="value">从 S7 读取的原始对象值</param> /// <param name="value">从 S7 读取的原始对象值</param>
private void ConvertS7ValueToStringAndNumeric(VariableDto variable, object value) private void ConvertS7ValueToStringAndNumeric(VariableDto variable, string value)
{ {
if (value == null) if (value == null)
return; return;
string directConversion = null; string directConversion = null;
double numericValue = 0.0; double numericValue = 0.0;
if (variable.DataType == DataType.Bool)
switch (value)
{ {
case double d: numericValue=value.ToString()=="True"?1.0:0.0;
directConversion = d.ToString("G17", CultureInfo.InvariantCulture); directConversion = value.ToString();
numericValue = d; return;
break;
case float f:
directConversion = f.ToString("G9", CultureInfo.InvariantCulture);
numericValue = f;
break;
case int i:
directConversion = i.ToString(CultureInfo.InvariantCulture);
numericValue = i;
break;
case uint ui:
directConversion = ui.ToString(CultureInfo.InvariantCulture);
numericValue = ui;
break;
case short s:
directConversion = s.ToString(CultureInfo.InvariantCulture);
numericValue = s;
break;
case ushort us:
directConversion = us.ToString(CultureInfo.InvariantCulture);
numericValue = us;
break;
case byte b:
directConversion = b.ToString(CultureInfo.InvariantCulture);
numericValue = b;
break;
case sbyte sb:
directConversion = sb.ToString(CultureInfo.InvariantCulture);
numericValue = sb;
break;
case long l:
directConversion = l.ToString(CultureInfo.InvariantCulture);
numericValue = l;
break;
case ulong ul:
directConversion = ul.ToString(CultureInfo.InvariantCulture);
numericValue = ul;
break;
case bool boolValue:
directConversion = boolValue.ToString().ToLowerInvariant();
numericValue = boolValue ? 1.0 : 0.0;
break;
case string str:
directConversion = str;
if (double.TryParse(str, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsedFromStr))
{
numericValue = parsedFromStr;
}
break;
default:
_logger.LogWarning($"变量 {variable.Name} 读取到未预期的数据类型: {value.GetType().Name}, 值: {value}");
directConversion = value.ToString() ?? string.Empty;
if (double.TryParse(directConversion, NumberStyles.Float, CultureInfo.InvariantCulture, out var parsedFromObj))
{
numericValue = parsedFromObj;
}
break;
} }
variable.DataValue = directConversion ?? value.ToString() ?? string.Empty; variable.DataValue = directConversion ?? value.ToString() ?? string.Empty;
variable.NumericValue = numericValue; variable.NumericValue = numericValue;
} }

View File

@@ -9,5 +9,6 @@ public class VariableHistory
public int VariableId { get; set; } public int VariableId { get; set; }
public Variable Variable { get; set; } public Variable Variable { get; set; }
public string Value { get; set; } // 以字符串形式存储,便于通用性 public string Value { get; set; } // 以字符串形式存储,便于通用性
public double NumericValue { get; set; }
public DateTime Timestamp { get; set; } public DateTime Timestamp { get; set; }
} }

View File

@@ -5,14 +5,20 @@ namespace DMS.Infrastructure.Data;
public class SqlSugarDbContext public class SqlSugarDbContext
{ {
private readonly SqlSugarClient _db; private readonly AppSettings _settings;
public SqlSugarDbContext(AppSettings settings) public SqlSugarDbContext(AppSettings settings)
{ {
var connectionString = settings.ToConnectionString(); _settings = settings;
var dbType = (SqlSugar.DbType)Enum.Parse(typeof(SqlSugar.DbType), settings.Database.DbType); }
_db = new SqlSugarClient(new ConnectionConfig
public SqlSugarClient GetInstance()
{
var connectionString = _settings.ToConnectionString();
var dbType = (SqlSugar.DbType)Enum.Parse(typeof(SqlSugar.DbType), _settings.Database.DbType);
return new SqlSugarClient(new ConnectionConfig
{ {
ConnectionString = connectionString, ConnectionString = connectionString,
DbType = dbType, DbType = dbType,
@@ -20,10 +26,4 @@ public class SqlSugarDbContext
InitKeyType = InitKeyType.Attribute InitKeyType = InitKeyType.Attribute
}); });
} }
public SqlSugarClient GetInstance()
{
return _db;
}
} }

View File

@@ -9,5 +9,6 @@ public class DbVariableHistory
public long Id { get; set; } public long Id { get; set; }
public int VariableId { get; set; } public int VariableId { get; set; }
public string Value { get; set; } public string Value { get; set; }
public double NumericValue { get; set; }
public DateTime Timestamp { get; set; } public DateTime Timestamp { get; set; }
} }