将包中定义的UDT作为参数传递给Oracle中的存储过程

时间:2013-03-14 21:34:54

标签: oracle parameter-passing user-defined-types custom-collection

创建一个包以定义自定义集合和具有此自定义集合的存储过程作为输入参数。如何从c#中调用此proc?

这是包裹:

CREATE OR REPLACE PACKAGE pkg_name
AS
    TYPE customCollectionType IS VARRAY(200) OF VARCHAR2 (1000);

    PROCEDURE ProcName(p_collection IN customCollectionType);
END pkg_name;
/
CREATE OR REPLACE PACKAGE BODY pkg_name
AS
    PROCEDURE StudyProc (p_StudyNum   IN     customCollectionType)
    IS
    ........................
END pkg_name;

这是customCollectionType的工厂实现:

public class PlaceHolderType : IOracleCustomType, INullable
{
    [OracleArrayMapping()]
    public string[] Array;
    private bool m_bIsNull;
    private OracleUdtStatus[] m_statusArray;

    public OracleUdtStatus[] StatusArray
    {
        get
        {
            return this.m_statusArray;
        }
        set
        {
            this.m_statusArray = value;
        }
    }

    public virtual bool IsNull
    {
        get
        {
            return m_bIsNull;
        }
    }

    public static PlaceHolderType Null
    {
        get
        {
            PlaceHolderType p = new PlaceHolderType();
            p.m_bIsNull = true;
            return p;
        }
    }

    public virtual void FromCustomObject(OracleConnection con, IntPtr pUdt)
    {
        OracleUdt.SetValue(con, pUdt, 0, Array, m_statusArray);
        return;
    }

    public virtual void ToCustomObject(OracleConnection con, IntPtr pUdt)
    {
        object objectStatusArray = null;
        Array = (string[])OracleUdt.GetValue(con, pUdt, 0, out objectStatusArray);
        m_statusArray = (OracleUdtStatus[])objectStatusArray;
    }

    public override string ToString()
    {
        return string.Empty;
    }
}

[OracleCustomTypeMappingAttribute("USER_NAME.PKG_NAME.CUSTOMCOLLECTIONTYPE")]
public class CUSTOMCOLLECTIONTYPE: IOracleCustomTypeFactory, IOracleArrayTypeFactory
{
    // Implementation of IOracleCustomTypeFactory.CreateObject()
    public IOracleCustomType CreateObject()
    {
        // Return a new custom object
        //OracleString or;
        return new PlaceHolderType();
    }

    #region IOracleArrayTypeFactory Members
    public Array CreateArray(int numElems)
    {
        return new string[numElems];
    }

    public Array CreateStatusArray(int numElems)
    {
        return new OracleUdtStatus[numElems];
    }

    #endregion
}

这是电话:

cmd.Connection = OracleConnectionObj;
cmd.BindByName = true;
cmd.CommandText = "PKG_NAME.PROC_NAME";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
OracleParameter param1 = new OracleParameter();
Array inputValue = (new CUSTOMCOLLECTIONTYPE()).CreateArray(5);
System.Array.Copy(SomeArray, inputValue, 5);
param1.OracleDbType = OracleDbType.Array;
param1.Direction = ParameterDirection.Input;
param1.UdtTypeName = "USER_NAME.CUSTOMCOLLECTIONTYPE";
param1.Value = inputValue;
cmd.Parameters.Add(param1);
cmd.ExecuteNonQuery();

.Net中的错误是:

“OCI-22303:输入\”USER_NAME \“。\”CUSTOMCOLLECTIONTYPE \“未找到”

1 个答案:

答案 0 :(得分:0)

当您将对象从C#传递给映射到UDT的过程时,您需要在架构级别而不是在包级别定义类型。因此,您需要在sqlplus中执行以下命令: -

Create Type customCollectionType AS VARRAY(200) OF VARCHAR2 (1000);

并从包规范中删除customCollectionType的声明。