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

EF Core结合Oracle使用Skip和Take报错ORA-00933求助

解决Oracle.EntityFrameworkCore中Skip/Take导致ORA-00933错误的问题

问题场景

使用Oracle.EntityFrameworkCore NuGet包时,编写带Skip和Take的LINQ查询:

var q = db.Set<T>()
    .FilterBy(filtri)
    .Skip(0)
    .Take(10);      

生成的SQL被包装在PL/SQL块中,触发**ORA-00933(SQL命令未正确结束)**错误:

DECLARE 
l_sql     varchar2(32767);
l_cur     pls_integer;
l_execute pls_integer;

BEGIN
l_cur := dbms_sql.open_cursor;
l_sql := 'SELECT &quot;w&quot;.&quot;REQUESTNUM&quot;, ...&quot;
FROM &quot;MP2&quot;.&quot;WOREQ&quot; &quot;w&quot;
WHERE ((&quot;w&quot;.&quot;SITEID&quot; = ''TESTCC'') AND (&quot;w&quot;.&quot;TASKNUM&quot; = ''AAAQ''))
OFFSET :p_0 ROWS FETCH NEXT :p_1 ROWS ONLY';
dbms_sql.parse(l_cur, l_sql, dbms_sql.native);
dbms_sql.bind_variable(l_cur, ':p_0', 0);
dbms_sql.bind_variable(l_cur, ':p_1', 10);
l_execute:= dbms_sql.execute(l_cur);
dbms_sql.return_result(l_cur);
END;

去掉Skip和Take后,生成的普通SQL可正常执行:

SELECT &quot;w&quot;.&quot;REQUESTNUM&quot;, ... 
FROM &quot;MP2&quot;.&quot;WOREQ&quot; &quot;w&quot;
WHERE ((&quot;w&quot;.&quot;SITEID&quot; = 'TESTCC') AND (&quot;w&quot;.&quot;TASKNUM&quot; = ''AAAQ''))

原因分析

从生成的PL/SQL代码能看到,l_sql变量的字符串存在语法错误:SELECT行末尾多了一个未闭合的双引号(...&quot;),导致整个SQL语句格式不完整,触发ORA-00933错误。这是Oracle EF Core驱动在生成带分页的PL/SQL包装代码时的潜在bug。

解决方法

  • 升级Oracle.EntityFrameworkCore版本
    该问题大概率是驱动版本的已知bug,建议升级到最新稳定版。Oracle官方后续版本修复了不少SQL生成的语法问题,升级后分页语句的PL/SQL包装逻辑会修正这个引号错误。

  • 禁用PL/SQL包装生成
    如果暂时无法升级,可以通过配置禁用EF Core对查询的PL/SQL包装,让驱动直接生成纯SQL语句而非PL/SQL块。在DbContext的OnConfiguring方法中添加配置:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseOracle("your_connection_string", 
            o => o.UseOracleSQLCompatibility("12") // 确保使用Oracle 12c+的分页语法
                  .DisablePLSQLWrapping()); // 禁用PL/SQL包装
    }
    

    注意:UseOracleSQLCompatibility("12")是因为OFFSET/FETCH语法从Oracle 12c开始支持,需确保你的数据库版本≥12c。

  • 替换Skip(0)为条件判断
    如果Skip的参数是0,可以通过代码逻辑跳过Skip调用,因为Skip(0)不会改变查询结果,反而可能触发驱动的错误分支:

    var query = db.Set<T>().FilterBy(filtri);
    if (skipCount > 0)
    {
        query = query.Skip(skipCount);
    }
    query = query.Take(10);
    

    这种方式避免了生成带Skip(0)的分页语句,绕过了驱动的bug场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 04:43:12