C#调用Oracle存储过程从ref cursor提取多条XML的实现方法
C# 提取Oracle Ref Cursor返回XML数据的实现方案
核心问题说明:存储过程中通过XMLELEMENT生成的列是原生XMLType类型,不是普通字符串,直接按字符串类型读取会触发类型不匹配错误,必须通过ODP.NET驱动提供的专用类型读取。
前置依赖
使用官方Oracle提供的ODP.NET驱动,不要使用微软已废弃多年的System.Data.OracleClient:
- .NET Framework环境:安装
Oracle.ManagedDataAccessNuget包 - .NET Core/.NET 5+环境:安装
Oracle.ManagedDataAccess.CoreNuget包
实现代码
using Oracle.ManagedDataAccess.Client; using Oracle.ManagedDataAccess.Types; using System.Collections.Generic; using System; public List<string> FetchDateRangeXml(DateTime startDate, DateTime endDate, string oracleConnStr) { List<string> xmlList = new List<string>(); using (OracleConnection conn = new OracleConnection(oracleConnStr)) { conn.Open(); using (OracleCommand cmd = new OracleCommand("GET_XML_DATERANGE", conn)) { cmd.CommandType = System.Data.CommandType.StoredProcedure; // 配置入参,日期类型直接传DateTime即可,不需要手动转字符串 cmd.Parameters.Add("start_date", OracleDbType.Date).Value = startDate; cmd.Parameters.Add("end_date", OracleDbType.Date).Value = endDate; // 配置输出Ref游标参数 cmd.Parameters.Add(new OracleParameter("p_cursor_xml", OracleDbType.RefCursor) { Direction = System.Data.ParameterDirection.Output }); using (OracleDataReader dr = cmd.ExecuteReader()) { while (dr.Read()) { // 按OracleXmlType类型读取字段,不要直接调用dr.GetString(0) OracleXmlType xmlData = dr.GetOracleXmlType(0); // 提取XML字符串,如需直接操作XML对象可调用xmlData.GetXmlDocument() xmlList.Add(xmlData.Value); } } } } return xmlList; }
注意事项
- 不要在存储过程中将
XMLType强制转换为VARCHAR2返回,XML内容长度超过Oracle长度限制时会出现截断、报错问题,直接返回原生XMLType由驱动解析最稳定。 - 如果出现类型转换错误,可在读取时调用
dr.GetFieldType(0).FullName确认字段类型,确认是Oracle.ManagedDataAccess.Types.OracleXmlType后再按对应方法读取。 - 部分低版本ODP.NET驱动存在语句缓存导致游标类型映射异常的问题,可在连接字符串中添加
Statement Cache Size=0临时排查。
内容的提问来源于stack exchange,提问作者MaxPayne999
相关产品推荐
相关产品推荐

