Oracle UDTs Custom type mapping for is not specified or is invalid

你。 提交于 2020-01-16 04:52:07

问题


I got this error, "Custom type mapping for 'ClassXX' is not specified or is invalid. Is it possible that my member value type is not correct to match db UDTs?

Here is my Code:

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

UDTs:

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

The Exception log is

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

回答1:


I tried simple roundtrip and everything seems to work fine.

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


来源:https://stackoverflow.com/questions/32409546/oracle-udts-custom-type-mapping-for-is-not-specified-or-is-invalid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!