Oracle高级队列C#中UDT入队报错:无法设置无效值'text'
排查Oracle AQ UDT入队错误:无法设置无效值'text'
这个错误的核心原因是Oracle标识符大小写不匹配——Oracle默认会将未用双引号包裹的字段名转换为大写,而你的C#代码中使用了小写的字段名进行映射,导致Oracle无法找到对应的UDT字段。
具体修改步骤:
修正UDT字段映射的大小写
将所有OracleObjectMapping特性的参数、OracleUdt.SetValue和OracleUdt.GetValue中的字段名改为大写(对应数据库中实际存储的字段名)。调整类的访问修饰符
将db_Message_type2类改为public,确保工厂类可以正确实例化它(虽然在同一命名空间下可以访问,但显式声明更规范)。移除重复的类型映射(可选)
你同时在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
相关产品推荐
相关产品推荐

