SqlSugar查询字符串转成Int的问题
业务场景:点击事件触发vm的插入方法,vm的插入方法调用SqlSugar查询方法,查询当前ParamName的Sequence的最大值+1,再执行SqlSugar插入方法。
Sequence实体类字段为String,数据库表字段为varchar(密码的谁tm把有“排序”意义的东西搞成string的,所有值均为“Int ”1-N这种)
被恶心了记录一下
错误代码
            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。
基本确定是查询语句问题。
分析
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- 筛选(Where):从ConfGuide表中筛选出ParamName等于currentParamName的所有记录(例如ParamName=测试的 12 条记录)。
 - 提取字段(Select):从筛选结果中仅提取Sequence字段,得到一个字符串类型的序列(例如["1","2","3",...,"12"])。
 - 取最大值(Max):对这个字符串序列中的每个元素,通过SqlFunc.ToInt32(t)转换为 int,再取最大值。
 - 计算新值(+1):将最大值加 1,作为新记录的Sequence。
 
核心问题:转换时机错误,导致按 “字符串规则” 取最大值
这段代码的致命问题是:先提取字符串类型的Sequence,再尝试转换为 int 取最大值。
但 SqlSugar 在解析这种查询时,会在数据库层面先对字符串类型的Sequence取最大值(按字符串排序),再执行转换,而非 “先转换为 int 再取最大值”。
- 字符串排序规则:比较字符的 ASCII 码,例如"12"的第一个字符是'1',"2"的第一个字符是'2',因此"12" < "2"(字符串层面)。
 - 最终结果:数据库中ParamName=测试的Sequence字符串最大值是"2",转换为 int 后是2,加 1 后得到3(但你的实际场景中甚至直接返回2,说明转换逻辑未生效)。
 
修改代码1:
int maxSequence = _db.Queryable<ConfGuide>().Where(t => t.ParamName == currentParamName) // 筛选条件:匹配当前ParamName.Max(t => SqlFunc.ToInt32(t.Sequence)); // 关键:直接对每条记录的Sequence先转换为int,再取最大值
可见执行成功
分析:
- 筛选(Where):同第一段,筛选出
ParamName=currentParamName的所有记录。 - 直接取最大值(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 值按 “数字规则” 取最大值(例如
12是1到12中的最大值)。 
最终得到正确的最大 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
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
逻辑解析:
- 筛选(Where):和原代码一致,筛选出
ParamName匹配的记录(如ParamName=测试的 12 条记录)。 - 提取并转换(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])。 - 取最大值(Max):由于
Select后已是 int 序列,直接调用Max()即可得到 int 类型的最大值(如12),加 1 后得到新的Sequence(如13)。 
为什么这样能解决问题?
- 原第一段代码的问题是:
Select提取的是 string 序列,Max阶段的转换无法改变 “数据库先按字符串排序取最大值” 的逻辑; - 修改后:
Select阶段就将序列转换为 int 类型,Max操作直接对 int 序列生效,数据库会按 “数字排序” 取最大值(如12是1-12中的最大值),符合业务预期。 
和第二段代码的区别(仅结构差异):
- 第二段代码是
Where后直接用Max(t => 转换逻辑),属于 “直接对原始实体字段计算最大值”; - 此修改方案是
Where→Select(转换)→Max(),属于 “先转换为目标类型序列,再取最大值”,结构上更贴近你最初的代码习惯,但效果完全一致。 
