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

LINQ查询中用运算符比较SQLite的decimal失败,CompareTo可行

问题:SQLite中Decimal列LINQ比较报错,CompareTo却能运行的原因?

问题背景

我在SQLite数据库中有一张Foo表,其中包含数据类型为decimal的Bar列。想要检索Bar值大于100的所有行,执行以下LINQ查询时出现翻译错误:

var result = from r in db.Foo
             where r.Bar > 100
             select r.Bar;

错误信息

The LINQ expression 'DbSet.Where(r => r.Bar > 100)' could not be translated.

Either rewrite the query in a form that can be translated,
or switch to client evaluation explicitly by inserting a call to either
AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().

改用CompareTo方法改写查询后,却能正常执行:

var result = from r in db.Foo
             where r.Bar.CompareTo(100) > 0
             select r;

我疑惑二者逻辑一致但结果不同,想知道CompareTo是否触发了客户端求值?


解答

1. EF Core对SQLite Decimal类型的翻译限制

SQLite没有原生的decimal/numeric数据类型,EF Core会将.NET的decimal映射为SQLite的TEXT或REAL类型(具体取决于配置)。当直接使用>运算符比较decimal列与数值时,EF Core的查询翻译器无法将这个操作转换为SQLite兼容的语法,导致翻译失败。

2. CompareTo方法的翻译逻辑

EF Core的查询翻译器对CompareTo方法有专门的处理规则,它可以将r.Bar.CompareTo(100) > 0翻译为SQLite能识别的比较语句:

  • 如果Bar映射为TEXT类型,会生成字符串比较的SQL(SQLite中存储decimal为文本时,字典序比较可保证数值顺序);
  • 如果映射为REAL类型,则生成数值比较的SQL。

这个过程是服务器端求值,没有触发客户端求值。

3. 验证是否触发客户端求值

你可以通过查看EF Core生成的SQL语句确认:

var query = from r in db.Foo
            where r.Bar.CompareTo(100) > 0
            select r;
Console.WriteLine(query.ToQueryString());

输出的SQL会包含针对Bar列的比较逻辑,说明查询是在数据库端执行的,而非拉取所有数据到本地过滤。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 17:35:07