本次提交包含了两个主要部分:一个关键的数据库并发问题修复,以及一个关于历史记录功能的增强。
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:
@@ -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; }
|
||||||
}
|
}
|
||||||
@@ -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 // 记录当前时间
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user