Friday, May 30, 2008

Oracle's SDO_DIM_ARRAY as UDT and utilizing SDO_MIGRATE.TO_CURRENT as stored procedure

Author: Jonio, Dennis

Utilizing Oracle’s latest ODP for .NET the following is one implementation of the SDO_DIM_ARRAY and SDO_DIM_ELEMENT type(s) as a .NET class.

This one is easy to explain. I needed to use SDO_MIGRATE.TO_CURRENT to fix some ORA-13367: wrong orientation for interior/exterior rings errors. So I needed SDO_DIM_ARRAY and thusly SDO_DIM_ELEMENT because SDO_MIGRATE.TO_CURRENT requires a SDO_DIM_ARRAY as a parameter. I have included my method of utilizing SDO_MIGRATE.TO_CURRENT after the class definitions.

Source code (C#):
As you see, it utilizes both sdogeometry and sdodimarray...

2 comments:

  1. I get memory leaks using udt this way

    It seems like oracle is not releasing the reference to the data in the OracleUdt

    Have you seen that

    I am sending large amount of data to a procedure
    so in a short time the size of my application becomes big, windows is then not behaving in a good way

    I am glad if there is a solution to this

    /Bengt

    ReplyDelete
  2. Here is some code I have done
    First the array class



    public class UdtArray T : IOracleCustomType, INullable
    where T : IOracleCustomType
    {

    [OracleObjectMapping(0)]
    public T[] _listElements;
    private bool m_bIsNull;
    public bool IsNull
    {
    get { return m_bIsNull; }
    }

    public T[] ListElements
    {
    get { return _listElements; }
    set { _listElements = value; }
    }

    public static UdtArray T Null
    {
    get
    {
    UdtArray T obj = new UdtArray T();
    obj.m_bIsNull = true;
    return obj;
    }
    }

    public override string ToString()
    {
    if (m_bIsNull)
    {
    return "UdtArray.Null";
    }
    else
    {
    StringBuilder sb = new StringBuilder();
    foreach (T i in _listElements)
    {
    sb.Append("UdtArray(");
    sb.Append(i.ToString() + "=");
    sb.Append(")");
    }
    return sb.ToString();
    }
    }

    public virtual void ToCustomObject(OracleConnection con, IntPtr pUdt)
    {
    _listElements = (T[])OracleUdt.GetValue(con, pUdt, 0);
    }

    public virtual void FromCustomObject(OracleConnection con, IntPtr pUdt)
    {
    OracleUdt.SetValue(con, pUdt, 0, (T[])_listElements);
    }

    public Array CreateStatusArray(int numElems)
    {
    return null;
    }
    }


    /////////
    // the data in the array

    public class UdtTransDetail : IOracleCustomType, INullable
    {
    [OracleObjectMapping(0)]
    public long TransdetailId;
    [OracleObjectMapping(1)]
    public long TransactionId;
    [OracleObjectMapping(2)]
    public DateTime ReportedStartTime;
    [OracleObjectMapping(3)]
    public DateTime ReportedEndTime;
    [OracleObjectMapping(4)]
    public DateTime RatedStartTime;
    [OracleObjectMapping(5)]
    public DateTime RatedEndTime;
    [OracleObjectMapping(6)]
    public decimal Units;

    public UdtTransDetail()
    {
    }

    public UdtTransDetail(UtTransDetailDataMD2 data, long transactionid, long transdetailid)
    {
    TransdetailId = transdetailid;
    TransactionId = transactionid;
    ReportedStartTime = data.ReportedStartTime;
    ReportedEndTime = data.ReportedEndTime;
    RatedStartTime = data.RatedStartTime; // this will be set in db just a dummy add
    RatedEndTime = data.RatedEndTime; // this will be set in db just a dummy add
    Units = data.Units;
    }

    private bool m_bIsNull;
    public bool IsNull
    {
    get { return m_bIsNull; }
    }


    public static UdtTransDetail Null
    {
    get
    {
    UdtTransDetail obj = new UdtTransDetail();
    obj.m_bIsNull = true;
    return obj;
    }
    }

    public override string ToString()
    {
    if (m_bIsNull)
    {
    return "UdtTransDetail.Null";
    }
    else
    {

    StringBuilder sb = new StringBuilder();
    sb.Append("UdtTransDetail(");
    sb.Append(")");
    return sb.ToString();
    }
    }

    public virtual void ToCustomObject(OracleConnection con, IntPtr pUdt)
    {
    TransdetailId = (long)OracleUdt.GetValue(con, pUdt, 0);
    TransactionId = (long)OracleUdt.GetValue(con, pUdt, 1);
    ReportedStartTime = (DateTime)OracleUdt.GetValue(con, pUdt, 2);
    ReportedEndTime = (DateTime)OracleUdt.GetValue(con, pUdt, 3);
    RatedStartTime = (DateTime)OracleUdt.GetValue(con, pUdt, 4);
    RatedEndTime = (DateTime)OracleUdt.GetValue(con, pUdt, 5);
    Units = (decimal)OracleUdt.GetValue(con, pUdt, 6);
    }

    public virtual void FromCustomObject(OracleConnection con, IntPtr pUdt)
    {
    OracleUdt.SetValue(con, pUdt, 0, TransdetailId);
    OracleUdt.SetValue(con, pUdt, 1, TransactionId);
    OracleUdt.SetValue(con, pUdt, 2, ReportedStartTime);
    OracleUdt.SetValue(con, pUdt, 3, ReportedEndTime);
    OracleUdt.SetValue(con, pUdt, 4, RatedStartTime);
    OracleUdt.SetValue(con, pUdt, 5, RatedEndTime);
    OracleUdt.SetValue(con, pUdt, 6, Units);
    }

    }




    ////the factory


    /// For Details

    public class DetailUdtFactory : IOracleCustomTypeFactory
    {
    public IOracleCustomType CreateObject()
    {
    UdtTransDetail sdodimelement = new UdtTransDetail();
    return sdodimelement;
    }
    }

    public class DetailUdtArrayFactory : IOracleArrayTypeFactory, IOracleCustomTypeFactory
    {
    public IOracleCustomType CreateObject()
    {
    return new UdtArray UdtTransDetail();
    }

    public Array CreateArray(int numElems)
    {
    return new UdtTransDetail[numElems];
    }

    public Array CreateStatusArray(int numElems)
    {
    return null;
    }
    }





    The procedure has six arays as argument this is
    I use the UDTArray for all of them


    Anyone knows this ???

    /Bengt

    ReplyDelete