首页 游戏 软件 资讯 排行榜 专题
首页
数据库
.NET如何调用带复杂参数的Oracle存储过程_自定义类型

.NET如何调用带复杂参数的Oracle存储过程_自定义类型

热心网友
48
转载
2026-04-17

Oracle UDT 与 Table Type 使用指南:数据库预创建与 ODP.NET 参数配置详解

Oracle UDT 和 Table Type 必须在数据库中预先创建

在 C# 应用程序中调用 Oracle 存储过程时,如果涉及自定义对象类型(UDT)或表类型(Table Type),必须确保这些类型已在 Oracle 数据库中成功创建并处于有效状态。若数据库端类型定义缺失或无效,即使 C# 代码参数配置正确,系统仍会抛出 ORA-04043: object ... does not existORA-00902: invalid datatype 等错误。问题的核心在于数据库对象不存在,而非代码逻辑错误。

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

.NET如何调用带复杂参数的Oracle存储过程_自定义类型

因此,在编写 C# 调用代码之前,务必在 Oracle 数据库中完成以下验证:

  • 确认对象类型(OBJECT)已通过 CREATE OR REPLACE TYPE ... AS OBJECT 语句成功创建,且状态为 VALID
  • 确认表类型(TABLE OF ...)已通过 CREATE OR REPLACE TYPE ... AS TABLE OF ... 语句创建,并且其依赖的基础对象类型已存在。

常见错误场景是:先创建了 student_table_type,却未创建其依赖的 student_obj_type。这种情况下,程序可能在连接阶段不报错,但在执行存储过程时,会因类型解析失败而提示“类型不存在”。

ODP.NET 中传递 Table Type 需使用 OracleCollectionType.PLSQLAssociativeArray

在 .NET 中调用 Oracle 存储过程并传递表类型参数时,必须使用 Oracle 官方的 ODP.NET 数据提供程序(即 Oracle.ManagedDataAccess 库)。已过时的 System.Data.OracleClient 无法识别 PL/SQL 关联数组,不应继续使用。

配置 ODP.NET 参数时,需重点关注以下三个要点:

  • 必须将 OracleParameter.CollectionType 属性设置为 OracleCollectionType.PLSQLAssociativeArray,而非 PLSQLNestedTable 或其他选项。
  • OracleParameter.Value 必须赋值为 .NET 数组(如 object[] 或具体类型的数组),直接传入 ListIEnumerable 集合将导致错误。
  • 存储过程中对应的输入参数必须声明为 IN my_table_type 形式,且 my_table_type 必须是数据库中已定义的 TABLE OF ... 类型。

以下是一个配置示例:

var students = new object[] {
    new object[] { 1, "Alice", DateTime.Now },
    new object[] { 2, "Bob", DateTime.Now }
};
var param = new OracleParameter("p_students", OracleDbType.Object);
param.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
param.UdtTypeName = "STUDENT_TABLE_TYPE"; // 注意:类型名需全大写,严格匹配数据库定义
param.Value = students;

UDT 对象数组需映射至 .NET 类并注册 OracleUdtMapping

若要传递自定义对象类型(如 TestObjType),而非简单字段组合,则必须为 ODP.NET 建立 .NET 类与 Oracle 对象类型之间的映射关系。仅在 C# 中定义类是不够的,必须进行显式的映射注册,否则无法正确序列化与反序列化数据。

映射注册主要有两种方式:

  • 全局注册(推荐):在应用程序启动时(如 Main 方法或 Global.asax 中)调用 OracleUdtMapping.Add 方法,一次性完成所有自定义类型的映射注册。
  • 局部注册:在每次创建数据库连接前手动注册映射。此方式易遗漏,增加维护复杂度,一般不推荐。

注册代码示例如下(需确保命名空间、属性顺序及大小写与数据库定义完全一致):

[OracleCustomTypeMapping("SCHEMA.TESTOBJTYPE")]
public class TestObjType : IOracleCustomType
{
    public decimal? ID { get; set; }
    public string Name { get; set; }
    public DateTime? CreateTime { get; set; }
    public string Status { get; set; }
    public string Description { get; set; }

    public void FromCustomObject(OracleConnection con, IntPtr pUdt)
    {
        // 实现字段写入逻辑
    }
    public void ToCustomObject(OracleConnection con, IntPtr pUdt)
    {
        // 实现字段读取逻辑
    }
}

// 在应用启动时注册映射:
OracleUdtMapping.Add(new OracleUdtMapping{
    UdtTypeName = "SCHEMA.TESTOBJTYPE",
    CSharpTypeName = typeof(TestObjType).AssemblyQualifiedName
});

若遗漏 [OracleCustomTypeMapping] 特性,或注册时类型名大小写不匹配(如数据库定义为 TESTOBJTYPE,代码中误写为 TestObjType),可能导致 ORA-03113: end-of-file on communication channel 错误或静默失败。

输出参数为 UDT 时,OracleParameter.Direction 须设为 Output 且不预设 Value

当存储过程返回 TABLE OF ... 类型的结果集时,输出参数的配置是常见错误点。若为输出参数预先赋值(如 param.Value = new object[0]),ODP.NET 会尝试向 Oracle 写入该空数组,从而引发类型不匹配异常。

正确的配置步骤如下:

  • Direction 属性设置为 ParameterDirection.Output
  • 保持 Value 属性为空(不进行赋值)
  • 命令执行完毕后,从 param.Value 属性中读取返回的 OracleUdtobject[] 数组

假设存储过程定义如下:

PROCEDURE get_students(p_out OUT student_table_type)

则 C# 端应如下配置:

var outParam = new OracleParameter("p_out", OracleDbType.Object);
outParam.Direction = ParameterDirection.Output;
outParam.UdtTypeName = "STUDENT_TABLE_TYPE";
outParam.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
cmd.Parameters.Add(outParam);

cmd.ExecuteNonQuery();

// 执行完成后读取结果:
var resultArray = (object[])outParam.Value;

需注意一个细节:UDT 输出结果中的每个元素默认是 OracleUdt 实例,不会自动转换为已定义的 .NET 类——除非已实现并注册完整的序列化逻辑。若直接进行强制类型转换,将抛出 InvalidCastException 异常。

来源:https://www.php.cn/faq/2346412.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

Oracle RAC如何处理节点驱逐(Eviction)?优化心跳超时阈值
数据库
Oracle RAC如何处理节点驱逐(Eviction)?优化心跳超时阈值

Oracle RAC 节点驱逐的真正触发条件是什么? 在 Oracle RAC 集群环境中,许多管理员存在一个普遍误解,认为“网络心跳丢包”会直接引发节点驱逐。实际上,Oracle RAC 的驱逐机制远比这复杂和严谨。驱逐的核心决策者是 cssd(集群同步服务守护进程),它如同一个高度可靠的裁判,会

热心网友
04.17
Oracle RAC集群元数据损坏怎么修?强制清除crs资源
数据库
Oracle RAC集群元数据损坏怎么修?强制清除crs资源

ORA-40001元数据损坏修复指南:强制清除OCR资源记录与OCR损坏恢复方案 crsctl delete resource 删除失败报 ORA-40001 错误解析 当Oracle集群的元数据发生损坏时,执行 crsctl delete resource 命令通常会直接返回 ORA-40001:

热心网友
04.16
Oracle RAC如何处理ASM磁盘故障?替换并重新同步数据
数据库
Oracle RAC如何处理ASM磁盘故障?替换并重新同步数据

ASM磁盘离线处理机制详解:MISSING状态、自动修复与重平衡流程 ASM磁盘掉线后,RAC节点是否会自动移除故障磁盘? 答案是不会自动踢出。当ASM检测到磁盘不可访问时,会立即将其状态标记为 MISSING,并触发快速镜像同步功能——前提是该磁盘组已启用此特性,且故障属于临时性中断,例如网络闪断

热心网友
04.16
Oracle RAC如何执行集群健康检查?运行cluvfy脚本验证
数据库
Oracle RAC如何执行集群健康检查?运行cluvfy脚本验证

cluvfy sh 能检查什么,不能检查什么 首先需要明确:cluvfy sh 是 Oracle 官方提供的集群验证工具,但其本质是一个“静态环境”检查器,而非实时监控系统。它的核心价值在于,在执行关键操作(如 Oracle RAC 安装、升级、添加节点)之前,对系统环境进行一次全面的“合规性快照”

热心网友
04.16
Oracle RMAN恢复提示ORA-01157怎么处理_检查缺失的数据文件
数据库
Oracle RMAN恢复提示ORA-01157怎么处理_检查缺失的数据文件

ORA-01157表示控制文件记录了数据文件但物理上不可访问,恢复后仍报错通常因未执行RECOVER DATABASE和ALTER DATABASE OPEN RESETLOGS、路径不一致、权限不足或ASM别名失效。 ORA-01157 是什么,为什么恢复后还会报这个错 ORA-01157错误的核

热心网友
04.15

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

如何利用“清算热力图”预判大盘变盘点?实战操作指南
web3.0
如何利用“清算热力图”预判大盘变盘点?实战操作指南

清算热力图实战指南:精准预判加密市场变盘点的五大核心步骤 在波动剧烈的加密货币合约市场中,清算热力图正成为专业交易者洞察市场潜在“火药桶”的关键可视化工具。它通过动态展示不同价格区间的潜在清算头寸密度,将多空杠杆博弈的脆弱地带清晰呈现。掌握其核心用法,能有效辅助交易者识别价格可能发生剧烈转向或加速突

热心网友
04.17
不做成新罐头RPG!曝《刺客信条4:黑旗 重制版》坚守经典玩法
游戏评测
不做成新罐头RPG!曝《刺客信条4:黑旗 重制版》坚守经典玩法

《刺客信条:黑旗 Resynced》2026年发售,经典海盗传奇完全重制回归 据知名游戏爆料人Tom Henderson最新透露,备受玩家期待的《刺客信条:黑旗 Resynced》已正式定档,将于2026年7月9日全球同步发售。需要明确的是,本次项目并非简单的高清复刻版,而是对爱德华·肯威经典加勒比

热心网友
04.17
币安Binance现货合约交易官网入口 币安安卓苹果App下载注册与认证指南
web3.0
币安Binance现货合约交易官网入口 币安安卓苹果App下载注册与认证指南

币安Binance现货合约交易官网入口、App下载、注册与认证全指南 对于想要进入加密货币交易世界的新手来说,找到正确的起点至关重要。本文将为你清晰指引币安(Binance)的官方入口,并手把手带你完成从下载App、注册账户到完成身份认证的全过程。所有步骤都基于官方渠道,确保你的每一步操作都安全、可

热心网友
04.17
洛克王国世界前期哪个神宠比较好
游戏攻略
洛克王国世界前期哪个神宠比较好

洛克王国新手开局必看:前期神宠选择攻略与重要性解析 对于刚刚踏入洛克王国的新手玩家来说,开局阶段选择一只强力的前期神宠,是决定冒险旅程是否顺畅的关键。一只优秀的前期宠物不仅能让你轻松应对主线任务和日常挑战,更能帮助你快速理解游戏的核心战斗机制与属性克制关系。那么,在洛克王国前期,哪些宠物值得优先培养

热心网友
04.17
币圈合约中的“强平引擎”是如何运作的?保险基金起到什么作用?
web3.0
币圈合约中的“强平引擎”是如何运作的?保险基金起到什么作用?

深度解析:Web3合约交易中的强平引擎与保险基金核心机制 在波澜云诡的加密货币合约交易市场中,“强制平仓”是每一位交易者都极力避免却又必须深刻理解的风险事件。这背后并非一个简单的风控开关,而是一套被称为“强平引擎”的复杂、自动化、多层级风险管理系统。它的高效运作,直接关系到交易平台的稳健性与用户的资

热心网友
04.17