ODP.net将UDT作为表传递给C#中的存储过程

时间:2015-10-25 01:40:47

标签: c# oracle oracle-sqldeveloper odp.net

我有一个自定义类型,看起来像这样

create or replace TYPE order_type AS OBJECT
(
   order_type VARCHAR2 (50),
   quantity VARCHAR2 (50),
   price NUMBER,

);

表定义如下

create or replace TYPE order_tabtype AS TABLE OF order_type;

存储过程

  PROCEDURE create_order (acc_number  VARCHAR2,
                            order_items devs.order_tabtype,
                            confirmation_num OUT VARCHAR2)
   IS

我应该如何准备我的C#类以使我的存储过程调用工作。 我提到的大多数示例要么将UDT作为数组传递,要么只有默认类型的表。但是我需要将自定义类型作为表传递。

1 个答案:

答案 0 :(得分:5)

这是我在ODP.NET演示中用于UDT的简单示例。这是在表中传递三个UDT实例作为绑定变量:

void Main()
{
    using (var connection = new OracleConnection("DATA SOURCE=hq_pdb_tcp;PASSWORD=oracle;USER ID=HUSQVIK"))
    {
        connection.Open();

        using (var command = connection.CreateCommand())
        {
            command.CommandText = "DECLARE x SYS.ODCISECOBJTABLE := :p; BEGIN :r := x.COUNT; END;";

            var parameter = command.CreateParameter();
            parameter.Direction = ParameterDirection.Input;
            parameter.ParameterName = "p";
            parameter.OracleDbType = OracleDbType.Array;
            parameter.UdtTypeName = "SYS.ODCISECOBJTABLE";
            parameter.Value =
                new OdciSecObjTable
                {
                    Values = new OdciSecObj[]
                    {
                        new OdciSecObj { POBJSCHEMA = "V1", POBJNAME = "V2", OBJSCHEMA = "V3", OBJNAME = "V4" },
                        new OdciSecObj { POBJSCHEMA = "V5", POBJNAME = "V6", OBJSCHEMA = "V7", OBJNAME = "V8" },
                        new OdciSecObj { POBJSCHEMA = "V9", POBJNAME = "V10", OBJSCHEMA = "V11", OBJNAME = "V12" }
                    }
                };

            command.Parameters.Add(parameter);

            var resultParameter = command.CreateParameter();
            resultParameter.Direction = ParameterDirection.Output;
            resultParameter.ParameterName = "r";
            resultParameter.OracleDbType = OracleDbType.Decimal;

            command.Parameters.Add(resultParameter);

            command.ExecuteNonQuery();
            Console.WriteLine(((OracleDecimal)resultParameter.Value).Value);
        }
    }
}

[OracleCustomTypeMapping("SYS.ODCISECOBJTABLE")]
public class OdciSecObjTable : CustomCollectionTypeBase<OdciSecObjTable, OdciSecObj>
{
}

[OracleCustomTypeMapping("SYS.ODCISECOBJ")]
public class OdciSecObj : CustomTypeBase<OdciSecObj>
{
    [OracleObjectMapping("POBJSCHEMA")]
    public string POBJSCHEMA;
    [OracleObjectMapping("POBJNAME")]
    public string POBJNAME;
    [OracleObjectMapping("OBJSCHEMA")]
    public string OBJSCHEMA;
    [OracleObjectMapping("OBJNAME")]
    public string OBJNAME;

    public override void FromCustomObject(OracleConnection connection, IntPtr pointerUdt)
    {
        OracleUdt.SetValue(connection, pointerUdt, "POBJSCHEMA", POBJSCHEMA);
        OracleUdt.SetValue(connection, pointerUdt, "POBJNAME", POBJNAME);
        OracleUdt.SetValue(connection, pointerUdt, "OBJSCHEMA", OBJSCHEMA);
        OracleUdt.SetValue(connection, pointerUdt, "OBJNAME", OBJNAME);
    }

    public override void ToCustomObject(OracleConnection connection, IntPtr pointerUdt)
    {
        POBJSCHEMA = (string)OracleUdt.GetValue(connection, pointerUdt, "POBJSCHEMA");
        POBJNAME = (string)OracleUdt.GetValue(connection, pointerUdt, "POBJNAME");
        OBJSCHEMA = (string)OracleUdt.GetValue(connection, pointerUdt, "OBJSCHEMA");
        OBJNAME = (string)OracleUdt.GetValue(connection, pointerUdt, "OBJNAME");
    }
}

public abstract class CustomCollectionTypeBase<TType, TValue> : CustomTypeBase<TType>, IOracleArrayTypeFactory where TType : CustomTypeBase<TType>, new()
{
    [OracleArrayMapping()]
    public TValue[] Values;

    public override void FromCustomObject(OracleConnection connection, IntPtr pointerUdt)
    {
        OracleUdt.SetValue(connection, pointerUdt, 0, Values);
    }

    public override void ToCustomObject(OracleConnection connection, IntPtr pointerUdt)
    {
        Values = (TValue[])OracleUdt.GetValue(connection, pointerUdt, 0);
    }

    public Array CreateArray(int elementCount)
    {
        return new TValue[elementCount];
    }

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

public abstract class CustomTypeBase<T> : IOracleCustomType, IOracleCustomTypeFactory, INullable where T : CustomTypeBase<T>, new()
{
    private bool _isNull;

    public IOracleCustomType CreateObject()
    {
        return new T();
    }

    public abstract void FromCustomObject(OracleConnection connection, IntPtr pointerUdt);

    public abstract void ToCustomObject(OracleConnection connection, IntPtr pointerUdt);

    public bool IsNull
    {
        get { return this._isNull; }
    }

    public static T Null
    {
        get { return new T { _isNull = true }; }
    }
}