You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor+MySQL环境下动态公式存储与C#解析计算方案咨询

方案解答

一、MySQL公式存储最优表结构

推荐用两张表解耦公式本身、变量取数逻辑,扩展性和可维护性更高:

1. 公式主表 formulas

存储公式核心元数据

字段名类型说明
idINT UNSIGNED AUTO_INCREMENT PRIMARY KEY主键
formula_nameVARCHAR(100) NOT NULL用户自定义的公式名称,用于前端展示
normalized_expressionTEXT NOT NULL标准化后的公式表达式,将用户输入的变量名替换为统一占位符,例如 ({meter_xyz123_kwh} - {meter_abc789_kwh}) / 2
raw_user_inputTEXT NOT NULL存储用户原始输入的公式内容,用于编辑回显
is_enabledTINYINT(1) DEFAULT 1后台调度任务是否启用该公式
create_timeDATETIME DEFAULT CURRENT_TIMESTAMP创建时间
update_timeDATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP更新时间

2. 公式变量映射表 formula_variables

存储公式中每个变量对应的数据源取数规则,和公式主表一对多关联

字段名类型说明
idINT UNSIGNED AUTO_INCREMENT PRIMARY KEY主键
formula_idINT UNSIGNED NOT NULL关联公式主表id,外键
placeholderVARCHAR(50) NOT NULL对应标准化表达式中的占位符,例如 meter_xyz123_kwh
display_nameVARCHAR(100) NOT NULL用户输入的变量显示名,例如 KWH value of meter xyz123
fetch_configJSON NOT NULL该变量的MySQL取数规则,示例:{"table":"meter_history","column":"kwh","filter":"meter_sn = 'xyz123' AND stat_date = CURRENT_DATE"}

二、公式解析实现方案

1. 开源NuGet包方案(推荐,开发成本低)

.NET5生态下有成熟的表达式解析库可以直接用,无需自己造轮子:

  • NCalc:轻量级、文档完善,完全覆盖基础算术运算需求,支持参数注入、语法校验,示例代码如下:
// 从数据库拿到标准化公式和变量实际取值
var normalizedExp = "({meter_xyz123_kwh} - {meter_abc789_kwh}) / 2";
var exp = new NCalc.Expression(normalizedExp);
// 注入从MySQL查询到的变量值
exp.Parameters["meter_xyz123_kwh"] = 125.6;
exp.Parameters["meter_abc789_kwh"] = 83.2;
// 计算结果,可提前调用HasErrors()方法做语法校验
var result = Convert.ToDecimal(exp.Evaluate());
  • DynamicExpresso:性能略优于NCalc,语法更贴近C#原生,同样支持.NET5,适合后续需要扩展自定义函数的场景。

2. .NET5原生工具实现方案

如果不能引入第三方依赖,也可以用.NET自带的System.Linq.Expressions表达式树实现,不过需要自行开发词法解析、语法校验逻辑:

  • 第一步:实现简单的词法分析器,将公式拆分为操作符、数值、变量三类Token
  • 第二步:按照算术优先级(括号>乘除>加减)把Token转换为表达式树节点,变量节点绑定从MySQL查询到的实际值
  • 第三步:编译表达式树为可执行委托,调用得到计算结果
    该方案仅适合公式规则固定、无复杂扩展需求的场景,否则自定义解析逻辑的维护成本很高。

内容的提问来源于stack exchange,提问作者Tom Boudniatski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 07:18:02