SqlSugar查询字符串转成Int的问题

业务场景:点击事件触发vm的插入方法,vm的插入方法调用SqlSugar查询方法,查询当前ParamName的Sequence的最大值+1,再执行SqlSugar插入方法。

Sequence实体类字段为String,数据库表字段为varchar(密码的谁tm把有"排序"意义的东西搞成string的,所有值均为"Int "1-N这种)

被恶心了记录一下

错误代码

cs 复制代码
            int maxSequence = _db.Queryable<ConfGuide>()
                .Where(t => t.ParamName == currentParamName)
                .Select(t => t.Sequence)
                .Max(t => SqlFunc.ToInt32(t)) + 1;

查询一个一共只有1行的paramName的Sequence字段,连续点击页面,输出的maxSequence一直为2。

查询一个一共有12行的paramName的Sequence字段,连续点击页面,输出的maxSequence也一直为2。

基本确定是查询语句问题。

分析

cs 复制代码
int maxSequence = _db.Queryable<ConfGuide>()
    .Where(t => t.ParamName == currentParamName) // 筛选条件:匹配当前ParamName
    .Select(t => t.Sequence) // 提取Sequence字段(string类型)
    .Max(t => SqlFunc.ToInt32(t)) + 1; // 对提取的string序列转换为int后取最大值,再加1
  1. 筛选(Where) :从ConfGuide表中筛选出ParamName等于currentParamName的所有记录(例如ParamName=测试的 12 条记录)。
  2. 提取字段(Select) :从筛选结果中仅提取Sequence字段,得到一个字符串类型的序列 (例如["1","2","3",...,"12"])。
  3. 取最大值(Max) :对这个字符串序列中的每个元素,通过SqlFunc.ToInt32(t)转换为 int,再取最大值。
  4. 计算新值(+1) :将最大值加 1,作为新记录的Sequence。
核心问题:转换时机错误,导致按 "字符串规则" 取最大值

这段代码的致命问题是:先提取字符串类型的 Sequence ,再尝试转换为 int 取最大值。

但 SqlSugar 在解析这种查询时,会在数据库层面先对字符串类型的 Sequence 取最大值 (按字符串排序),再执行转换,而非 "先转换为 int 再取最大值"。

  • 字符串排序规则:比较字符的 ASCII 码,例如"12"的第一个字符是'1',"2"的第一个字符是'2',因此"12" < "2"(字符串层面)。
  • 最终结果:数据库中ParamName=测试的Sequence字符串最大值是"2",转换为 int 后是2,加 1 后得到3(但你的实际场景中甚至直接返回2,说明转换逻辑未生效)。

修改代码1:

cs 复制代码
int maxSequence = _db.Queryable<ConfGuide>()
    .Where(t => t.ParamName == currentParamName) // 筛选条件:匹配当前ParamName
    .Max(t => SqlFunc.ToInt32(t.Sequence)); // 关键:直接对每条记录的Sequence先转换为int,再取最大值

可见执行成功

分析:

  1. 筛选(Where) :同第一段,筛选出ParamName=currentParamName的所有记录。
  2. 直接取最大值(Max) :对筛选出的每条记录,先通过SqlFunc.ToInt32(t.Sequence)Sequence(string)转换为 int(例如"12"12"2"2),再对转换后的 int 值取最大值。
解决问题的核心:转换时机提前,按 "数字规则" 取最大值

这段代码的关键是将 "转换为 int" 的操作嵌入到Max方法的表达式中,SqlSugar 会生成正确的 SQL,在数据库层面执行:

  • 先将每条记录的Sequence(string)转换为 int(例如CAST(Sequence AS INT));
  • 再对转换后的 int 值按 "数字规则" 取最大值(例如12112中的最大值)。

最终得到正确的最大 int 值(如12),后续加 1 后即可生成递增的新Sequence(如13)。

两段代码的本质差异

维度 第一段代码(错误) 第二段代码(正确)
转换与取最大值的顺序 先取字符串的最大值,再转换为 int 先将每个字符串转换为 int,再取 int 的最大值
数据库执行逻辑 按字符串排序取最大值(如"2"["1","12",...]的最大值) 按数字排序取最大值(如12[1,2,...,12]的最大值)
适用场景 仅适用于Sequence为字符串且按字符串排序符合预期的场景 适用于Sequence为字符串但存储数字,需按数字排序的场景

总结

业务场景中,Sequence是 "存储数字的字符串",需要按数字规则排序取最大值。第一段代码因 "先取字符串最大值再转换" 导致结果错误;第二段代码通过 "先转换为数字再取最大值",符合业务逻辑,最终解决了Sequence不递增的问题。

修改代码2:

在第一段代码的结构基础上(先Select提取字段,再对结果取最大值),要实现 "先将Sequence转换为 int,再取最大值",核心是Select阶段就完成类型转换 ,确保后续Max操作是针对 "int 类型的序列",而非 "string 类型的序列"。

具体修改(保持第一段代码的链式结构):

csharp

cs 复制代码
int maxSequence = _db.Queryable<ConfGuide>()
    .Where(t => t.ParamName == currentParamName) // 1. 筛选指定ParamName的记录
    .Select(t => SqlFunc.ToInt32(t.Sequence)) // 2. 提取时直接转换为int(关键修改)
    .Max() + 1; // 3. 对转换后的int序列取最大值,再加1

逻辑解析:

  1. 筛选(Where) :和原代码一致,筛选出ParamName匹配的记录(如ParamName=测试的 12 条记录)。
  2. 提取并转换(Select) :原代码的Select(t => t.Sequence)提取的是string类型的Sequence(如"1","2",..."12");修改后通过Select(t => SqlFunc.ToInt32(t.Sequence)),在提取时直接将每条记录的Sequence转换为 int 类型(如"12"12"2"2),此时查询结果变为int 类型的序列[1,2,3,...,12])。
  3. 取最大值(Max) :由于Select后已是 int 序列,直接调用Max()即可得到 int 类型的最大值(如12),加 1 后得到新的Sequence(如13)。

为什么这样能解决问题?

  • 原第一段代码的问题是:Select提取的是 string 序列,Max阶段的转换无法改变 "数据库先按字符串排序取最大值" 的逻辑;
  • 修改后:Select阶段就将序列转换为 int 类型,Max操作直接对 int 序列生效,数据库会按 "数字排序" 取最大值(如121-12中的最大值),符合业务预期。

和第二段代码的区别(仅结构差异):

  • 第二段代码是Where后直接用Max(t => 转换逻辑),属于 "直接对原始实体字段计算最大值";
  • 此修改方案是Where→Select(转换)→Max(),属于 "先转换为目标类型序列,再取最大值",结构上更贴近你最初的代码习惯,但效果完全一致。
相关推荐
Eiceblue3 小时前
通过 C# 将 HTML 转换为 RTF 富文本格式
开发语言·c#·html
IUGEI3 小时前
synchronized的工作机制是怎样的?深入解析synchronized底层原理
java·开发语言·后端·c#
czhc11400756636 小时前
C# 1124 接收
开发语言·c#
时光追逐者7 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 62 期(2025年11.17-11.23)
c#·.net·.netcore
司铭鸿7 小时前
祖先关系的数学重构:从家谱到算法的思维跃迁
开发语言·数据结构·人工智能·算法·重构·c#·哈希算法
宝桥南山11 小时前
.NET 10 - Blazor web assembly应用的一些诊断方式
microsoft·微软·c#·asp.net·.net·.netcore
m0_6265352012 小时前
代码分析
开发语言·c#
FuckPatience14 小时前
.netcoreapp2.0与.Net Core是什么关系
c#·.net·.netcore
Dr.勿忘14 小时前
开源Unity小框架:高效单例与模块化设计
游戏·unity·开源·c#·游戏引擎·游戏程序·gamejam