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

C#传递UDT对象数组至Oracle存储过程触发‘Column contains NULL data’异常

问题原因及解决办法

核心原因1:Oracle数组类型与C#参数配置不匹配

你在Oracle包中定义的T_EMTEST_ARRAY是嵌套表(table of EMTEST),但C#端参数的CollectionType设置为OracleCollectionType.PLSQLAssociativeArray,这两种类型不兼容。PLSQL关联数组要求Oracle端必须定义为table of ... index by binary_integer,类型不匹配会导致数据序列化时出错,触发"Column contains NULL data"异常。

核心原因2:Employee类缺少无参构造函数

Oracle.ManagedDataAccess在处理UDT(自定义类型)时,需要通过无参构造函数实例化对象,你的Employee类仅提供了带参构造,这会导致UDT序列化/反序列化过程中无法正确创建实例,进而引发空数据相关的转换异常。

核心原因3:INullable接口实现及null值处理不当

  • Null属性返回的实例中,你给Id和Name设置了默认值(0和空字符串),而非保持null,不符合Oracle UDT的null语义。
  • FromCustomObject和ToCustomObject方法中未正确处理C# null与Oracle DBNull的转换,直接传递null会导致Oracle无法识别,触发异常。

具体解决步骤

步骤1:修正Oracle端数组类型为PLSQL关联数组

修改包头部的数组定义,添加index by binary_integer:

-- 包头部
type T_EMTEST_ARRAY is table of EMTEST index by binary_integer;

procedure TestGetObjectsBack(
        Employes in T_EMTEST_ARRAY,
        ResultTest OUT RC_Result
);

步骤2:修正Employee类的实现

添加无参构造函数,修正Null属性,完善null值处理逻辑:

[OracleCustomTypeMapping("EMTEST")]
public class Employee : IOracleCustomType, INullable
{
    // 必须添加无参构造函数,供Oracle驱动实例化对象
    public Employee() { }

    public Employee(int? id, string name)
    {
        Id = id;
        Name = name;
    }

    [OracleObjectMapping("Name")]
    public string Name { get; set; }

    [OracleObjectMapping("Id")]
    public int? Id { get; set; }

    public bool IsNull { get; set; }

    // 返回真正的Null实例,不设置任何字段值
    public static Employee Null => new Employee { IsNull = true };

    public void FromCustomObject(OracleConnection con, object udt)
    {
        // 将C# null转换为Oracle可识别的DBNull.Value
        OracleUdt.SetValue(con, udt, "Id", Id ?? DBNull.Value);
        OracleUdt.SetValue(con, udt, "Name", Name ?? DBNull.Value);
    }

    public void ToCustomObject(OracleConnection con, object udt)
    {
        // 将Oracle返回的DBNull转换为C# null
        var idValue = OracleUdt.GetValue(con, udt, "Id");
        Id = idValue == DBNull.Value ? null : (int?)idValue;

        var nameValue = OracleUdt.GetValue(con, udt, "Name");
        Name = nameValue == DBNull.Value ? null : (string)nameValue;
    }
}

步骤3:修正C#端参数配置

确保参数的OracleDbType与数组类型匹配,这里使用OracleDbType.Array:

var employeParam = new OracleParameter("Employes", OracleDbType.Array, ParameterDirection.Input);
employeParam.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
employeParam.Size = employeArray.Length;
employeParam.UdtTypeName = "PKS_CARAT.T_EMTEST_ARRAY";
employeParam.Value = employeArray;

完成以上修改后,重新测试调用,应该可以解决"Column contains NULL data"的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 18:40:56