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

Oracle高级队列C#中UDT入队报错:无法设置无效值'text'

排查Oracle AQ UDT入队错误:无法设置无效值'text'

这个错误的核心原因是Oracle标识符大小写不匹配——Oracle默认会将未用双引号包裹的字段名转换为大写,而你的C#代码中使用了小写的字段名进行映射,导致Oracle无法找到对应的UDT字段。

具体修改步骤:

  1. 修正UDT字段映射的大小写
    将所有OracleObjectMapping特性的参数、OracleUdt.SetValue和OracleUdt.GetValue中的字段名改为大写(对应数据库中实际存储的字段名)。

  2. 调整类的访问修饰符
    将db_Message_type2类改为public,确保工厂类可以正确实例化它(虽然在同一命名空间下可以访问,但显式声明更规范)。

  3. 移除重复的类型映射(可选)
    你同时在db_Message_type2类和QueueMessageTypeFactory类上添加了OracleCustomTypeMapping,保留其中一个即可(推荐保留在UDT类上)。

修改后的完整代码:

UDT类(修正后)

[OracleCustomTypeMapping("APPS_GLOBAL.DB_MESSAGE_TYPE2")]
public class db_Message_type2 : IOracleCustomType, INullable {
    private string _text;
    private decimal _text1;
    private bool _isNull;

    public db_Message_type2() {
        _text = "iDontKnow";
        _text1 = 30;
    }

    public db_Message_type2(string text, decimal text1) {
        _text = text;
        _text1 = text1;
    }

    [OracleObjectMapping("TEXT")] // 改为大写TEXT
    public string text {
        get { return this._text; }
        set { this._text = value; }
    }

    [OracleObjectMapping("TEXT1")] // 改为大写TEXT1
    public decimal text1 {
        get { return this._text1; }
        set { this._text1 = value; }
    }

    public bool IsNull {
        get { return this._isNull; }
    }

    public void FromCustomObject(OracleConnection con, IntPtr pUdt) {
        // 字段名改为大写TEXT和TEXT1
        OracleUdt.SetValue(con, pUdt, "TEXT", this._text);
        OracleUdt.SetValue(con, pUdt, "TEXT1", this._text1);
    }

    public void ToCustomObject(OracleConnection con, IntPtr pUdt) {
        // 字段名改为大写TEXT和TEXT1
        text = (string)OracleUdt.GetValue(con, pUdt, "TEXT");
        text1 = (decimal)OracleUdt.GetValue(con, pUdt, "TEXT1");
    }

    public static db_Message_type2 Null {
        get { return new db_Message_type2 { _isNull = true }; }
    }
}

工厂类(修正后)

public class QueueMessageTypeFactory : IOracleCustomTypeFactory {
    public IOracleCustomType CreateObject() {
        var result = new db_Message_type2("iDontKnow anything about AQ", 50);
        return result;
    }
}

入队方法(优化后)

class Program {
    static void Main(string[] args) {
        EnqueueUDT();
        Console.ReadLine();
    }

    static void EnqueueUDT() {
        try {
            string _connstring = "myConnectionString";
            // 使用using语句自动释放资源,避免手动Dispose的冗余操作
            using (OracleConnection _connObj = new OracleConnection(_connstring)) {
                _connObj.Open();
                using (OracleTransaction _txn = _connObj.BeginTransaction()) {
                    using (OracleAQQueue _queueObj = new OracleAQQueue("APPS_GLOBAL.db_temp_adv_queue3", _connObj, OracleAQMessageType.Udt, "APPS_GLOBAL.DB_MESSAGE_TYPE2")) {
                        OracleAQMessage _msg = new OracleAQMessage();
                        _msg.Payload = new db_Message_type2 { text = "Custom", text1 = 5 };
                        _queueObj.Enqueue(_msg, new OracleAQEnqueueOptions { DeliveryMode = OracleAQMessageDeliveryMode.Persistent, Visibility = OracleAQVisibilityMode.Immediate });
                        _txn.Commit();
                    }
                }
            }
        } catch (Exception ex) {
            Console.WriteLine(ex.Message.ToString());
        }
    }
}

额外验证建议:

  • 确认数据库中的队列APPS_GLOBAL.db_temp_adv_queue3确实关联了APPS_GLOBAL.DB_MESSAGE_TYPE2类型,避免队列与消息类型不匹配的问题。
  • 如果你的UDT字段创建时用了双引号包裹(比如"text"),则需要严格保持C#映射字段名的大小写与数据库一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:19:27