Oracle UDTs的自定义类型映射未指定或无效
本文关键字:未指定 无效 映射 类型 UDTs 自定义 Oracle | 更新日期: 2023-09-27 18:11:13
我得到这个错误,"未指定'ClassXX'的自定义类型映射或无效。是否有可能我的成员值类型不正确匹配db udt ?
下面是我的代码:
ClassXX
[OracleCustomTypeMapping("DB.T_OUTERTRAN")]
public class ClassXX: AOracleCustomObject<ClassXX>
{
[OracleObjectMapping("OUTERSYSTEMCODE")]
public int OuterSystemCode { get; set; }
[OracleObjectMapping("TRANSACTIONSOURCE")]
public int TransactionSource { get; set; }
[OracleObjectMapping("TRANSACTIONTYPE")]
public int TransactionType { get; set; }
[OracleObjectMapping("AMOUNTCHANGE")]
public decimal AmountChange { get; set; }
[OracleObjectMapping("REFERENCENO")]
public string ReferenceNo { get; set; }
[OracleObjectMapping("REMARKS")]
public string Remarks { get; set; }
[OracleObjectMapping("VENDORID")]
public int VendorId { get; set; }
[OracleObjectMapping("BUID")]
public int BuId { get; set; }
[OracleObjectMapping("USERCODE")]
public string UserCode { get; set; }
[OracleObjectMapping("ACCEPTNEGATIVEBALANCE")]
public int AcceptNegativeBalance { get; set; }
protected override ClassXX _getObjInstance()
{
return this;
}
}
AOracleCustomObject:
public abstract class AOracleCustomObject<T> : INullable, IOracleCustomTypeFactory, IOracleCustomType
{
[IgnoreDataMember]
public bool IsNull
{
get
{
return false;
}
}
public void FromCustomObject(OracleConnection con, IntPtr pUdt)
{
T oracleObj = _getObjInstance();
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (PropertyInfo property in properties)
{
var attrs = (OracleObjectMappingAttribute[])
property.GetCustomAttributes(typeof(OracleObjectMappingAttribute), false);
if (attrs.Length > 0)
{
string attrName = attrs[0].AttributeName;
object value = property.GetValue(oracleObj, null);
OracleUdt.SetValue(con, pUdt, attrName, value);
}
}
}
public void ToCustomObject(OracleConnection con, IntPtr pUdt)
{
T oracleObj = _getObjInstance();
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (PropertyInfo property in properties)
{
var attrs = (OracleObjectMappingAttribute[])
property.GetCustomAttributes(typeof(OracleObjectMappingAttribute), false);
if (attrs.Length > 0)
{
string attrName = attrs[0].AttributeName;
Type ptype = property.PropertyType;
object value = Convert.ChangeType(OracleUdt.GetValue(con, pUdt, attrName), ptype);
property.SetValue(oracleObj, value, null);
}
}
}
public IOracleCustomType CreateObject()
{
return (IOracleCustomType)_getObjInstance();
}
protected abstract T _getObjInstance();
}
之上:
create or replace TYPE T_OUTERTRAN AS OBJECT
(
OUTERSYSTEMCODE NUMBER(4,0),
TRANSACTIONSOURCE NUMBER(4,0),
TRANSACTIONTYPE NUMBER(4,0),
AMOUNTCHANGE NUMBER(26,6),
REFERENCENO VARCHAR2(50 BYTE),
REMARKS VARCHAR2(100 BYTE),
VENDORID NUMBER(4,0),
BUID NUMBER(5,0),
USERCODE VARCHAR2(30 BYTE),
ACCEPTNEGATIVEBALANCE NUMBER(1,0)
);
异常日志是
Custom type mapping for 'ClassXX' is not specified or is invalid.
System.InvalidOperationException: Custom type mapping for 'ClassXX' is not specified or is invalid.
at Oracle.DataAccess.Types.OracleUdt.GetUdtName(String customTypeName, String dataSource)
at Oracle.DataAccess.Client.OracleParameter.SetUDTFromCustomObject(OracleConnection conn, IOracleCustomType customObj, Int32 i)
at Oracle.DataAccess.Client.OracleParameter.PreBind_Collection(OracleConnection conn)
at Oracle.DataAccess.Client.OracleParameter.PreBind(OracleConnection conn, IntPtr errCtx, Int32 arraySize)
at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()
我尝试了简单的往返,一切似乎都很好。
void Main()
{
using (var connection = new OracleConnection("DATA SOURCE=HQ_PDB_TCP;PASSWORD=oracle;USER ID=HUSQVIK"))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = "DECLARE i SYS.ODCICOST := :p; BEGIN :p := SYS.ODCICOST(i.CPUCOST + 1, i.IOCOST + 1, i.NETWORKCOST + 1, i.INDEXCOSTINFO || 'Dummy'); END;";
command.BindByName = true;
var parameter = command.CreateParameter();
parameter.Direction = ParameterDirection.InputOutput;
parameter.ParameterName = "p";
parameter.OracleDbType = OracleDbType.Object;
parameter.UdtTypeName = "SYS.ODCICOST";
parameter.Value = new OdciCost { CPUCOST = 123, INDEXCOSTINFO = "DUMMY", IOCOST = 456, NETWORKCOST = 789 };
command.Parameters.Add(parameter);
command.ExecuteNonQuery();
var odciCost = (OdciCost)parameter.Value;
Console.WriteLine($"CPUCOST={odciCost.CPUCOST}; IOCOST={odciCost.IOCOST}; NETWORKCOST={odciCost.NETWORKCOST}; INDEXCOSTINFO={odciCost.INDEXCOSTINFO}");
}
}
}
[OracleCustomTypeMapping("SYS.ODCICOST")]
public class OdciCost : IOracleCustomType, IOracleCustomTypeFactory, INullable
{
private bool _isNull;
[OracleObjectMapping("CPUCOST")]
public decimal CPUCOST;
[OracleObjectMapping("INDEXCOSTINFO")]
public string INDEXCOSTINFO;
[OracleObjectMapping("IOCOST")]
public decimal IOCOST;
[OracleObjectMapping("NETWORKCOST")]
public decimal NETWORKCOST;
public IOracleCustomType CreateObject()
{
return new OdciCost();
}
public void FromCustomObject(OracleConnection connection, IntPtr pointerUdt)
{
OracleUdt.SetValue(connection, pointerUdt, "CPUCOST", CPUCOST);
OracleUdt.SetValue(connection, pointerUdt, "IOCOST", IOCOST);
OracleUdt.SetValue(connection, pointerUdt, "NETWORKCOST", NETWORKCOST);
OracleUdt.SetValue(connection, pointerUdt, "INDEXCOSTINFO", INDEXCOSTINFO);
}
public void ToCustomObject(OracleConnection connection, IntPtr pointerUdt)
{
CPUCOST = (decimal)OracleUdt.GetValue(connection, pointerUdt, "CPUCOST");
IOCOST = (decimal)OracleUdt.GetValue(connection, pointerUdt, "IOCOST");
NETWORKCOST = (decimal)OracleUdt.GetValue(connection, pointerUdt, "NETWORKCOST");
INDEXCOSTINFO = (string)OracleUdt.GetValue(connection, pointerUdt, "INDEXCOSTINFO");
}
public bool IsNull
{
get { return this._isNull; }
}
public static OdciCost Null
{
get { return new OdciCost { _isNull = true }; }
}
}