При однократном вызове хранимой процедуры с массивом (вместо многократного вызова процедуры, которая принимает атомарные элементы), вы должны задать для OracleDbType значение Array. Значение устанавливается в соответствии со структурой базовых данных, как указано в пользовательском классе типа данных оракула. В данном случае это byte[][].
parameter.OracleDbType = OracleDbType.Array;
parameter.UdtTypeName = "GUIDARRAY";
parameter.Value = arrangedGuidList.ToArray();
// Note, do NOT set the collection type. Default it to "none"
Затем я определил свои пользовательские типы Oracle. См. здесь для примера. Я адаптировал классы SimpleVarray / SimpleVarrayFactory, чтобы они работали с Byte[][].
%ODAC_HOME%\ODACsamples\odp.net\4\UDT
Ключевой частью фабричного класса является то, что сопоставление пользовательского типа должно соответствовать свойству параметра UdtTypeName и состоять из заглавных букв. Похоже, что OracleCustomTypeMapping заставляет ODAC во время выполнения привязывать пользовательский тип, указанный в параметре, и создавать класс GuidArray где-то под капотом с помощью методов ToCustomObject/FromCustomObject.
[OracleCustomTypeMapping("GUIDARRAY")]
public class GuidArrayFactory : IOracleCustomTypeFactory, IOracleArrayTypeFactory
{
public IOracleCustomType CreateObject()
{
return new GuidArray();
}
// IOracleArrayTypeFactory Inteface
public Array CreateArray(int numElems)
{
return new Byte[numElems][];
}
public Array CreateStatusArray(int numElems)
{
// CreateStatusArray may return null if null status information
// is not required.
return new OracleUdtStatus[numElems];
}
}
-
// See %ODAC_HOME%\ODACsamples\odp.net\4\UDT
public class GuidArray : IOracleCustomType, INullable
{
[OracleArrayMapping]
public Byte[][] Array;
private OracleUdtStatus[] m_statusArray;
public OracleUdtStatus[] StatusArray
{
get
{
return m_statusArray;
}
set
{
m_statusArray = value;
}
}
private bool m_bIsNull;
public bool IsNull
{
get
{
return m_bIsNull;
}
}
public static GuidArray Null
{
get
{
GuidArray obj = new GuidArray();
obj.m_bIsNull = true;
return obj;
}
}
public void ToCustomObject(OracleConnection con, IntPtr pUdt)
{
object objectStatusArray = null;
Array = (Byte[][])OracleUdt.GetValue(con, pUdt, 0, out objectStatusArray);
m_statusArray = (OracleUdtStatus[])objectStatusArray;
}
public void FromCustomObject(OracleConnection con, IntPtr pUdt)
{
OracleUdt.SetValue(con, pUdt, 0, Array, m_statusArray);
}
public override string ToString()
{
if (m_bIsNull)
return "GuidArray.Null";
string rtnstr = String.Empty;
if (m_statusArray[0] == OracleUdtStatus.Null)
rtnstr = "NULL";
else
rtnstr = Array.GetValue(0).ToString();
for (int i = 1; i < m_statusArray.Length; i++)
{
if (m_statusArray[i] == OracleUdtStatus.Null)
rtnstr += "," + "NULL";
else
rtnstr += "," + Array.GetValue(i);
}
return "GuidArray(" + rtnstr + ")";
}
}
person
Stealth Rabbi
schedule
12.09.2013