ORA-00933错误本质是EF Core默认按Oracle 12c+语法生成OFFSET/FETCH分页SQL,而Oracle 11g不支持该语法;必须显式调用UseOracleSQLCompatibility("11")使EF Core回退生成ROWNUM嵌套查询。
EF Core 默认按 Oracle 12c+ 语法生成分页 SQL(OFFSET ... FETCH NEXT),但 Oracle 11g 不支持该语法,直接执行就会报 ORA-00933: SQL命令未正确结束。这不是连接问题或 Linq 写法错误,而是 EF Core 驱动层对数据库版本的默认假设与实际环境错配。
仅调用 UseOracle(connectionString) 不够——它默认走 12c 兼容模式。必须通过 UseOracleSQLCompatibility("11") 显式声明目标版本,EF Core 才会回退到 ROWNUM 嵌套子查询方式生成分页语句。
AddDbContextPool 中配置:options.UseOracle(conn, b => b.UseOracleSQLCompatibility("11"))
OnConfiguring,写法为:optionsBuilder.UseOracle(connectionString, b => b.UseOracleSQLCompatibility("11"))
"11",不是数字 11 或 "11g"
"12";混用 11g/12c 实例时,需按实际数据库版本分别配置即使设置了 UseOracleSQLCompatibility("11"),若对 FromSqlRaw() 结果再链式调用 Skip()/Take(),EF Core 仍可能尝试在外层包装 OFFSET——因为 FromSqlRaw 返回的是可组合 IQueryable,EF 不知道你已手动写了分页逻辑。
FromSqlRaw() 后立刻调用 AsEnumerable() 或 AsAsyncEnumerable(),切断 IQueryable 链,让 Skip/Take 在内存中执行ROWNUM 套壳),避免混合使用rownum 而非 OFFSET
如果你用 AddDbContextPool,同一个 DbContext 实例可能被多个请求复用。如果某次请求意外触发了未带 UseOracleSQLCompatibility 的配置路径(比如条件分支漏配),后续请求哪怕走正确路径,也可能因缓存或状态残留继续报错。
UseOracleSQLCompatibility
OnConfiguring 中根据环境变量动态决定是否调用该方法——一旦跳过,就彻底失效UseOracle 开始,版本兼容性就已经锁死了。