【问题标题】:Oracle in C#, bind variables, and queries like ID IN (1, 2, 3)C# 中的 Oracle、绑定变量和 ID IN (1, 2, 3) 等查询
【发布时间】:2015-10-06 13:47:33
【问题描述】:

我正在寻找对以下 Java 技术的 C# ODAC 改编,其中代码能够将数字数组(数组大小可以变化)绑定到非 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

【问题讨论】:

    标签: c# sql oracle odac bind-variables


    【解决方案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();
    

    其后是以下 Helper 类:

    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 表类型。如果其他类型需要它,您可能需要查找/编写其他自定义表类型。

    【讨论】:

    • 这直接进入了我们的代码库,我几乎没有任何工作!很好的发现。
    猜你喜欢
    • 2013-09-07
    • 2011-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-08
    • 2014-03-09
    • 1970-01-01
    相关资源
    最近更新 更多