在C#中使用Oracle,绑定变量和类似于ID IN(1、2、3)的查询

3
我正在寻找一个 C# ODAC 版本的以下 Java 技术的适应,代码能够将一个数字数组绑定到非 PL/SQL 的 SELECT 语句中,然后在 WHERE ID IN (...) 类型的检查中使用结果数组(数组大小可变)。

http://rafudb.blogspot.com/2011/10/variable-inlist.html

这是OCI-based C程序中使用该技术的另一个示例: Oracle OCI,绑定变量和类似ID IN(1, 2, 3)的查询 具体而言,我们想要执行像下面这样的查询:
SELECT * FROM MyTable WHERE ID IN (SELECT * FROM TABLE(:1))

将一个数字数组传递到:1中。
1个回答

3

代码:

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和自定义工厂/类才能成功绑定。

这受到了以下帖子中关于定义自定义类型的启发

限制:

这种解决方案仅适用于INT / NUMBER值,因为它是基于SYS.ODCINUMBERLIST表类型的附带效应。如果需要其他类型,则可能需要找到/编写其他自定义表类型。


1
这个东西几乎不需要我付出什么努力就可以直接放到我们的代码库中!发现得真好。 - StilesCrisis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接