C# 中的 Oracle,绑定变量和 ID IN (1, 2, 3) 之类的查询
Oracle in C#, bind variables, and queries like ID IN (1, 2, 3)
我正在寻找以下 Java 技术的 C# ODAC 改编版,其中代码能够将数字数组(数组大小可以变化)绑定到 non-PL/SQL SELECT
语句,然后在 WHERE ID IN (...)
样式检查中使用结果数组。
http://rafudb.blogspot.com/2011/10/variable-inlist.html
这是在基于 OCI 的 C 程序中使用此技术的另一个示例:
Oracle OCI, bind variables, and queries like ID IN (1, 2, 3)
具体来说,我们要执行这样的查询
SELECT * FROM MyTable WHERE ID IN (SELECT * FROM TABLE(:1))
并将数字数组传入:1
。
代码:
oraParam.UdtTypeName = "SYS.ODCINUMBERLIST";
VArray newArray = new VArray();
newArray.Array = new Int32[] {12,24,42};
oraParam.OracleDbType = OracleDbType.Array;
oraParam.Value = newArray;
string query = @"Select * from TABLE(:1) ";
OracleCommand command = new OracleCommand(query, MyConnection);
command.Parameters.Add(oraParam);
OracleDataReader reader;
var m_connection = new OracleConnection("The CONNECTION STRING");
m_connection.Open();
var reader = command.ExecuteReader();
reader.Close();
m_connection.Close();
随后是以下助手类:
class VArray : IOracleCustomType, INullable
{
[OracleArrayMapping()]
public Int32[] Array;
private OracleUdtStatus[] m_statusArray;
public OracleUdtStatus[] StatusArray
{
get
{
return this.m_statusArray;
}
set
{
this.m_statusArray = value;
}
}
private bool m_bIsNull;
public bool IsNull
{
get
{
return m_bIsNull;
}
}
public static VArray Null
{
get
{
VArray obj = new VArray();
obj.m_bIsNull = true;
return obj;
}
}
public void ToCustomObject(OracleConnection con, IntPtr pUdt)
{
object objectStatusArray = null;
Array = (Int32[])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 "VArray.Null";
else
{
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).ToString();
}
return "VArray(" + rtnstr + ")";
}
}
}
[OracleCustomTypeMapping("SYS.ODCINUMBERLIST")]
public class VArrayFactory : IOracleCustomTypeFactory, IOracleArrayTypeFactory
{
// IOracleCustomTypeFactory
public IOracleCustomType CreateObject()
{
return new VArray();
}
// IOracleArrayTypeFactory Interface
public Array CreateArray(int numElems)
{
return new Int32[numElems];
}
public Array CreateStatusArray(int numElems)
{
// CreateStatusArray may return null if null status information
// is not required.
return new OracleUdtStatus[numElems];
}
}
描述:
总体思路是,与 OCI 示例类似,您必须将参数转换为 SYS.ODCINUMBERLIST(或其他有效类型)。该类型默认情况下未在 C# OracleDBType 中定义,因此您必须使用 UdtTypeName 和自定义 Factory/Class 才能成功绑定。
灵感来自 following post on defining custom types。
限制:
这个精确的解决方案只适用于 INT/NUMBER 值,因为它搭载了 SYS.ODCINUMBERLIST table 类型。如果其他类型需要它,您可能需要 find/write 额外的自定义 table 类型。
我正在寻找以下 Java 技术的 C# ODAC 改编版,其中代码能够将数字数组(数组大小可以变化)绑定到 non-PL/SQL SELECT
语句,然后在 WHERE ID IN (...)
样式检查中使用结果数组。
http://rafudb.blogspot.com/2011/10/variable-inlist.html
这是在基于 OCI 的 C 程序中使用此技术的另一个示例:
Oracle OCI, bind variables, and queries like ID IN (1, 2, 3)
具体来说,我们要执行这样的查询
SELECT * FROM MyTable WHERE ID IN (SELECT * FROM TABLE(:1))
并将数字数组传入:1
。
代码:
oraParam.UdtTypeName = "SYS.ODCINUMBERLIST";
VArray newArray = new VArray();
newArray.Array = new Int32[] {12,24,42};
oraParam.OracleDbType = OracleDbType.Array;
oraParam.Value = newArray;
string query = @"Select * from TABLE(:1) ";
OracleCommand command = new OracleCommand(query, MyConnection);
command.Parameters.Add(oraParam);
OracleDataReader reader;
var m_connection = new OracleConnection("The CONNECTION STRING");
m_connection.Open();
var reader = command.ExecuteReader();
reader.Close();
m_connection.Close();
随后是以下助手类:
class VArray : IOracleCustomType, INullable
{
[OracleArrayMapping()]
public Int32[] Array;
private OracleUdtStatus[] m_statusArray;
public OracleUdtStatus[] StatusArray
{
get
{
return this.m_statusArray;
}
set
{
this.m_statusArray = value;
}
}
private bool m_bIsNull;
public bool IsNull
{
get
{
return m_bIsNull;
}
}
public static VArray Null
{
get
{
VArray obj = new VArray();
obj.m_bIsNull = true;
return obj;
}
}
public void ToCustomObject(OracleConnection con, IntPtr pUdt)
{
object objectStatusArray = null;
Array = (Int32[])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 "VArray.Null";
else
{
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).ToString();
}
return "VArray(" + rtnstr + ")";
}
}
}
[OracleCustomTypeMapping("SYS.ODCINUMBERLIST")]
public class VArrayFactory : IOracleCustomTypeFactory, IOracleArrayTypeFactory
{
// IOracleCustomTypeFactory
public IOracleCustomType CreateObject()
{
return new VArray();
}
// IOracleArrayTypeFactory Interface
public Array CreateArray(int numElems)
{
return new Int32[numElems];
}
public Array CreateStatusArray(int numElems)
{
// CreateStatusArray may return null if null status information
// is not required.
return new OracleUdtStatus[numElems];
}
}
描述:
总体思路是,与 OCI 示例类似,您必须将参数转换为 SYS.ODCINUMBERLIST(或其他有效类型)。该类型默认情况下未在 C# OracleDBType 中定义,因此您必须使用 UdtTypeName 和自定义 Factory/Class 才能成功绑定。
灵感来自 following post on defining custom types。
限制:
这个精确的解决方案只适用于 INT/NUMBER 值,因为它搭载了 SYS.ODCINUMBERLIST table 类型。如果其他类型需要它,您可能需要 find/write 额外的自定义 table 类型。