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#):
- using System;
- using System.Collections;
- using System.Text;
- using Oracle.DataAccess.Client;
- using Oracle.DataAccess.Types;
- namespace NetSdoDimArray
- {
- /// <summary>
- /// ////////////////////////////////////
- /// sdodimarray
- /// ////////////////////////////////////
- /// </summary>
- public class sdodimarray : IOracleCustomType, INullable
- {
- [OracleObjectMapping(0)]
- public sdodimelement[] _dimelements;
- private bool m_bIsNull;
- public bool IsNull
- {
- get
- {
- return m_bIsNull;
- }
- }
- public sdodimelement[] DimElements
- {
- get
- {
- return _dimelements;
- }
- set
- {
- _dimelements = value;
- }
- }
- public static sdodimarray Null
- {
- get
- {
- sdodimarray obj = new sdodimarray();
- obj.m_bIsNull = true;
- return obj;
- }
- }
- public override string ToString()
- {
- if (m_bIsNull)
- return "sdodimarray.Null";
- else
- {
- StringBuilder sb = new StringBuilder();
- foreach (sdodimelement i in _dimelements)
- {
- sb.Append("sdodimelement(");
- sb.Append(i._dimname + "=");
- sb.Append(string.Format("{0:0.#####}", i._lb));
- sb.Append(",");
- sb.Append(string.Format("{0:0.#####}", i._ub));
- sb.Append(",Tol=");
- sb.Append(i._tolerance.ToString());
- sb.Append(")");
- }
- return sb.ToString();
- }
- }
- public void ToCustomObject(OracleConnection con, IntPtr pUdt)
- {
- _dimelements = (sdodimelement[])OracleUdt.GetValue(con, pUdt, 0);
- }
- public void FromCustomObject(OracleConnection con, IntPtr pUdt)
- {
- OracleUdt.SetValue(con, pUdt, 0, _dimelements);
- }
- }
- [OracleCustomTypeMapping("MDSYS.SDO_DIM_ARRAY")]
- public class sdodimarrayFactory : IOracleArrayTypeFactory, IOracleCustomTypeFactory
- {
- // IOracleCustomTypeFactory Inteface
- public IOracleCustomType CreateObject()
- {
- return new sdodimarray();
- }
- // IOracleArrayTypeFactory.CreateArray Inteface
- public Array CreateArray(int numElems)
- {
- return new sdodimelement[numElems];
- }
- // IOracleArrayTypeFactory.CreateStatusArray
- public Array CreateStatusArray(int numElems)
- {
- // An OracleUdtStatus[] is not required to store null status information
- // if there is no NULL attribute data in the element array
- return null;
- }
- }
- /// <summary>
- /// ////////////////////////////////////
- /// sdodimelement
- /// ////////////////////////////////////
- /// </summary>
- public class sdodimelement : IOracleCustomType, INullable
- {
- [OracleObjectMapping(0)]
- public string _dimname;
- [OracleObjectMapping(1)]
- public double _lb;
- [OracleObjectMapping(2)]
- public double _ub;
- [OracleObjectMapping(3)]
- public double _tolerance;
- private bool m_bIsNull;
- public bool IsNull
- {
- get
- {
- return m_bIsNull;
- }
- }
- public static sdodimelement Null
- {
- get
- {
- sdodimelement obj = new sdodimelement();
- obj.m_bIsNull = true;
- return obj;
- }
- }
- public override string ToString()
- {
- if (m_bIsNull)
- return "sdodimelement.Null";
- else
- {
- StringBuilder sb = new StringBuilder();
- sb.Append("sdodimelement(");
- sb.Append(_dimname + "=");
- sb.Append(string.Format("{0:0.#####}", _lb));
- sb.Append(",");
- sb.Append(string.Format("{0:0.#####}", _ub));
- sb.Append(",Tol=");
- sb.Append(_tolerance.ToString());
- sb.Append(")");
- return sb.ToString();
- }
- }
- public void ToCustomObject(OracleConnection con, IntPtr pUdt)
- {
- _dimname = (string)OracleUdt.GetValue(con, pUdt, 0);
- _lb = (double)OracleUdt.GetValue(con, pUdt, 1);
- _ub = (double)OracleUdt.GetValue(con, pUdt, 2);
- _tolerance = (double)OracleUdt.GetValue(con, pUdt, 3);
- }
- public void FromCustomObject(OracleConnection con, IntPtr pUdt)
- {
- OracleUdt.SetValue(con, pUdt, 0, _dimname);
- OracleUdt.SetValue(con, pUdt, 1, _lb);
- OracleUdt.SetValue(con, pUdt, 2, _ub);
- OracleUdt.SetValue(con, pUdt, 3, _tolerance);
- }
- }
- [OracleCustomTypeMapping("MDSYS.SDO_DIM_ELEMENT")]
- public class sdodimelementFactory : IOracleCustomTypeFactory
- {
- // IOracleCustomTypeFactory Inteface
- public IOracleCustomType CreateObject()
- {
- sdodimelement sdodimelement = new sdodimelement();
- return sdodimelement;
- }
- }
- }
- public static sdogeometry MigrateToCurrentSP(string connectstring, sdogeometry _geoIn, sdodimarray _toleranceIn)
- {
- //ORA-13367: wrong orientation for interior/exterior rings
- sdogeometry rtnval = null;
- using (OracleConnection conn = new OracleConnection(connectstring))
- {
- using (OracleCommand dbcmd = conn.CreateCommand())
- {
- dbcmd.CommandType = CommandType.StoredProcedure;
- dbcmd.CommandText = "SDO_MIGRATE.TO_CURRENT";
- OracleParameter cParm1 = new OracleParameter();
- cParm1.ParameterName = "geometry";
- cParm1.OracleDbType = OracleDbType.Object;
- cParm1.Value = _geoIn;
- cParm1.UdtTypeName = "MDSYS.SDO_GEOMETRY";
- cParm1.Direction = ParameterDirection.Input;
- OracleParameter cParm2 = new OracleParameter();
- cParm2.ParameterName = "tolerance";
- cParm2.OracleDbType = OracleDbType.Object;
- cParm2.Value = _toleranceIn;
- cParm2.UdtTypeName = "MDSYS.SDO_DIM_ARRAY";
- cParm2.Direction = ParameterDirection.Input;
- OracleParameter cParm3 = new OracleParameter();
- cParm3.ParameterName = "RETURNVALUE";
- cParm3.OracleDbType = OracleDbType.Object;
- cParm3.UdtTypeName = "MDSYS.SDO_GEOMETRY";
- cParm3.Direction = ParameterDirection.ReturnValue;
- // Note the order
- dbcmd.Parameters.Add(cParm3);
- dbcmd.Parameters.Add(cParm1);
- dbcmd.Parameters.Add(cParm2);
- try
- {
- conn.Open();
- dbcmd.ExecuteNonQuery();
- rtnval = (sdogeometry)dbcmd.Parameters["RETURNVALUE"].Value;
- }
- catch (Exception _Ex)
- {
- throw (_Ex); // Actually rethrow
- }
- finally
- {
- if (conn != null && conn.State == ConnectionState.Open)
- {
- conn.Close();
- }
- }
- }//using cmd
- }//using conn
- return rtnval;
- }
I get memory leaks using udt this way
ReplyDeleteIt 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
Here is some code I have done
ReplyDeleteFirst 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