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()

Oracle UDTs的自定义类型映射未指定或无效

我尝试了简单的往返,一切似乎都很好。

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 }; }
    }
}