C#/Dapper 将 XML CLOB 传递给 Oracle 存储过程导致 LPX-00210

C# / Dapper passing XML CLOB to Oracle stored procedure causes LPX-00210

我正在开发一个批量加载程序,该程序需要将 10K 到 30K 行加载到多个 table 中。所采用的方法是将大型 XML 文件发送到存储过程。此存储过程从 XMLTABLE 执行 INSERT/SELECT 以加载 table.

当从 SQL 开发人员使用以下 XML 调用存储过程时,它运行良好:

<NMFC_CTL_STG>
<row><cust>CSA</cust><itemNbr>001010</itemNbr><sub>00</sub><seqNbr>0</seqNbr><status></status><effectiveDate>1995-08-26</effectiveDate><expirationDate></expirationDate></row>
</NMFC_CTL_STG>

当C#客户端生成上面的XML,将其保存成Unicode字符串作为byte[]放入Dapper OracleClob中,然后调用存储过程,出现如下错误:

C#代码:

using var connection = InvocationHelper.GetConnection();
var parameters = new OracleDynamicParameters();
var clobData = new OracleClob(connection as OracleConnection);

clobData.Write(bytes, 0, bytes.Length);

parameters.Add("pi_nmfc_data", bytes, OracleDbType.Clob, ParameterDirection.Input);

connection.Execute(procedureName, parameters, commandType: CommandType.StoredProcedure);

错误

Error: ORA-31011: XML parsing failed
ORA-19213: error occurred in XML processing at lines 1
LPX-00210: expected '<' instead of 'S'
ORA-06512: at "SYS.XMLTYPE", line 272
ORA-06512: at "RATES_PBLC.NMFC_IMPORTS", line 244
ORA-06512: at line 1

RATES_PBLC.NMFC_IMPORTS 的第 244 行是

l_nmfc_xml_blob := xmltype(pi_nmfc_data);

我根本无法弄清楚它正在寻找的 S。我确实查看了二进制数组,发现前两个字节是 255,254,这是字节顺序标记 (BOM)。我试着把它去掉,但仍然遇到同样的错误。我尝试将编码更改为 UTF-8,但存储过程一点也不喜欢。我确实看到了一些关于换行符的问题,所以我删除了那些但仍然得到同样的错误。

对这里发生的事情有什么建议吗?

您正在创建一个 OracleClob 对象,将一些数据从字节数组 bytes 写入其中,然后使用 bytes 作为调用 parameters.Add(...).

您是不是想使用 clobData 而不是 bytes 作为参数值?

您收到的错误消息是因为字符串 System.Byte[](即您在字节数组上调用 .ToString() 时得到的内容)被发送到存储过程。我通过编写一个调用 raise_application_error 并在消息中使用过程参数的存储过程来验证这一点,这就是错误消息中的内容。另外,我可以在 SQL*Plus.

中重现你的错误 运行 select xmltype('System.Byte[]') from dual

顺便说一句,您没有向我们展示您是如何在您的应用中创建 bytes 的,但在我的系统上我需要使用 Encoding.GetEncoding("UTF-16LE").GetBytes(...); 创建它。不过,这可能是我的 Oracle 数据库 (18c XE) 设置方式的人工产物。