繁体   English   中英

Oracle和C#-UDT数组作为返回值

Oracle and C# - UDT array as return value

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我正在尝试让C#读取PL / SQL用户定义类型的数组。

这是数组中每个对象的定义:

CREATE OR REPLACE TYPE "REPORTDATUM" AS OBJECT
(
            FIELD1                                                   VARCHAR2(20),
            FIELD2                                                   VARCHAR2(3000),
            FIELD3                                                   NUMBER(15),
            FIELD4                                                   DATE,
            FIELD5                                                   DATE,
            FIELD6                                                   VARCHAR2(4000),
            FIELD7                                                   TIMESTAMP,
            FIELD8                                                   VARCHAR2(10),
            FIELD9                                                   NUMBER(35),
            FIELD10                                                  VARCHAR2(80),
            FIELD11                                                  VARCHAR2(50)
);

CREATE OR REPLACE TYPE "REPORTARRAY" IS TABLE OF REPORTDATUM;

这是我要调用的函数的签名:

FUNCTION getReport(startTime IN DATE, endTime IN DATE) RETURN REPORTARRAY;

现在,根据我在这里找到的指南: http : //appsjack.blogspot.com/2010/09/pass-custom-udt-types-to-oracle-stored.html

我创建了ReportDatum.cs类,如下所示:

public class ReportDatum : INullable,  IOracleCustomType {

    private bool objectIsNull;

    [OracleObjectMappingAttribute(Constants.ReportDatum.Aliases.Field1)]
    public string Field1 { get; set; }

    [OracleObjectMappingAttribute(Constants.ReportDatum.Aliases.Field2)]
    public string Field2 { get; set; }

                            [...]

    [OracleObjectMappingAttribute(Constants.ReportDatum.Aliases.Field11)]
    public string Field11 { get; set; }


    public static ReportDatum Null {
        get {
            ReportDatum reportDatum = new ReportDatum();
            reportDatum.objectIsNull = true;
            return reportDatum;
        }
    }

    public bool IsNull {
        get { return objectIsNull; }
    }

    public void FromCustomObject(OracleConnection databaseConnection, IntPtr userDefinedTypePointer) {
        if (string.IsNullOrEmpty(this.Field1) == false ) {
            OracleUdt.SetValue(databaseConnection, userDefinedTypePointer, Constants.ReportDatum.Aliases.Field1, this.Field1);
        }
        if (string.IsNullOrEmpty(this.Field2) == false) {
            OracleUdt.SetValue(databaseConnection, userDefinedTypePointer, Constants.ReportDatum.Aliases.Field2, this.Field2);
        }
        [...]
        if (string.IsNullOrEmpty(this.Field11) == false) {
            OracleUdt.SetValue(databaseConnection, userDefinedTypePointer, Constants.ReportDatum.Aliases.Field11, this.Field11);
        }
    }

    public void ToCustomObject(OracleConnection databaseConnection, IntPtr userDefinedTypePointer) {
        this.Field1 = parseString(databaseConnection, userDefinedTypePointer, Constants.ReportDatum.Aliases.Field1);
        this.Field2 = parseString(databaseConnection, userDefinedTypePointer, Constants.ReportDatum.Aliases.Field2);
                                            [...]
        this.Field11 = parseString(databaseConnection, userDefinedTypePointer, Constants.ReportDatum.Aliases.Field11);
    }

    private string parseString(OracleConnection databaseConnection, IntPtr userDefinedTypePointer, string columnName) {
        string valueToReturn = String.Empty;
        try {
            valueToReturn = ( String ) OracleUdt.GetValue(databaseConnection, userDefinedTypePointer, columnName);
        }
        catch (Exception e) {
            error("Exception while attempting to parse string value of column [" + columnName + "]. Message [" + (e == null || e.Message == null ? "NULL" : e.Message) + "]", e);
        }
        return valueToReturn;
    }

 }

我还按照以下步骤创建ReportDatumFactory.cs:

public class ReportDatumFactory : IOracleCustomTypeFactory {

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

}

根据我上面链接的指南,这足以处理组成数组的每个项目。

为了处理数组本身,我创建了以下类。

ReportArray.cs

public class ReportArray : INullable, IOracleCustomType {

    [OracleArrayMapping()]
    public ReportDatum[] reportArray;

    private bool objectIsNull;

    public bool IsNull {
        get { return objectIsNull; }
    }

    public void FromCustomObject(OracleConnection databaseConnection, IntPtr userDefinedTypePointer) {
        try {
            OracleUdt.SetValue(databaseConnection, userDefinedTypePointer, 0, reportArray);
        }
        catch (Exception e) {
            error("Exception while populating OracleUdt from ReportArray.", e);
        }
    }

    public void ToCustomObject(OracleConnection databaseConnection, IntPtr userDefinedTypePointer) {
        try {
            reportArray = ( ReportDatum[] ) OracleUdt.GetValue(databaseConnection, userDefinedTypePointer, 0);
        }
        catch (Exception e) {
            error("Exception while reading values from OracleUdt related to ReportArray.", e);
        }
    }

}         

和相关的工厂类

ReportArrayFactory.cs

public class ReportArrayFactory : IOracleCustomTypeFactory, IOracleArrayTypeFactory {

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


    public Array CreateArray(int numberOfElements) {
        return new ReportArray[numberOfElements];
    }

    public Array CreateStatusArray(int numberOfElements) {
        return null;
    }

}

现在,关于调用存储过程的方法,这就是我所拥有的:

Report.cs

    private void executeStoredProcedure2(OracleConnection databaseConnection, string schema, string storedProcedureName, DateTime startTime, DateTime endTime, int numberOfElements) {
        OracleCommand databaseCommand = new OracleCommand();
        ReportArray reportArray = new ReportArray();

        debug("Attempting to populate the report array");
        if (databaseConnection != null && databaseConnection.State == ConnectionState.Open) {
            try {
                databaseCommand.Connection = databaseConnection;
                databaseCommand.CommandType = CommandType.StoredProcedure;
                databaseCommand.CommandText = schema + "." + storedProcedureName;
                databaseCommand.Parameters.Add(createUserDefinedParameter(numberOfElements, reportArray));
                databaseCommand.Parameters.Add(Constants.ReportDatum.ParameterNames.startTime, OracleDbType.Date, startTime, ParameterDirection.Input);
                databaseCommand.Parameters.Add(Constants.ReportDatum.ParameterNames.endTime, OracleDbType.Date, endTime, ParameterDirection.Input);
                databaseCommand.ExecuteNonQuery();
                //How do I populate the reportArray object?
            }
            catch (Exception exception) {
                error("Exception while executing stored procedure [" + storedProcedure2 + "].", exception);
            }
            finally {
                databaseCommand.Dispose();
            }
        }
    }



    private OracleParameter createUserDefinedParameter(int size, ReportArray reportArray) {
        OracleParameter valueToReturn = null;
        try {
            valueToReturn = new OracleParameter();
            valueToReturn.ParameterName = "reportData"; //this is the name of the REPORTARRAY object in the Oracle function that is being returned.
            valueToReturn.OracleDbType = OracleDbType.Array;
            valueToReturn.Direction = ParameterDirection.ReturnValue;
            valueToReturn.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
            valueToReturn.UdtTypeName = Constants.ReportDatum.arrayDataTypeDefinition;
            valueToReturn.ArrayBindSize = new int[size];
            valueToReturn.ArrayBindStatus = new OracleParameterStatus[size];
            valueToReturn.Size = size;
            valueToReturn.Value = reportArray.reportArray;
        }
        catch (Exception e) {
            error("Exception while attempting to create user defined parameter.", e);
        }
        return valueToReturn;
    }

我面临的问题是我无法使用C#返回数组。 有人遇到过这个问题吗? 我想念什么?

我有理由相信SQL代码可以正常工作。 目前只有C#产生了问题。

1 个回复

看起来有些错误。

首先,工厂需要OracleCustomTypeMapping属性。 没有它们,Oracle将根本不会使用这些映射工厂类:

    [OracleCustomTypeMapping("SCHEMA.REPORTDATUM")]
    public class ReportDatum ...

    [OracleCustomTypeMapping("SCHEMA.REPORTARRAY")]
    public class ReportArray ...

其次,数组映射工厂存在一个错误:创建数组时,您要创建一个ReportDatum对象数组。 目前,您正在创建一个ReportArray对象数组,即不需要的数组数组。 换句话说,替换

    public Array CreateArray(int numberOfElements) {
        return new ReportArray[numberOfElements];
    }

    public Array CreateArray(int numberOfElements) {
        return new ReportDatum[numberOfElements];
    }

第三,删除行

        CollectionType = OracleCollectionType.PLSQLAssociativeArray,

从您的createUserDefinedParameter方法。 返回的值不是PL / SQL关联数组(它是另一种集合),因此不应使用此属性。 如果使用此属性,则可能会发现从存储函数返回的返回值是一个空的object数组。

最后,要从存储的函数调用中获取数组,请在对databaseCommand.ExecuteNonQuery()的调用之后添加以下行:

    reportArray = (ReportArray)databaseCommand.Parameters["reportData"].Value;
1 无法从C#中的ORACLE函数获取返回值

以下是我从oracle函数获取价值的C#代码: 以下是我的Oracle功能: * 现在我的问题是,我无法从c#函数中的oracle函数获取返回值。 我从Oracle函数获得SQL开发人员的输出,但没有从C#代码获得输出。 如果我在c#中检查mgrParam.valu ...

3 oracle中插入和返回值

我需要在一个查询中插入并返回主键,这可能吗? 原因是主键是自动递增的,所以我不知道它是什么。 选择 PersonId :我插入的当前 ID。 谢谢, ...

4 从Oracle存储过程返回值

我在Oracle中有一个存储过程。 我希望如果成功更新记录,它将返回一个返回值1否则为0 。 让我知道我该怎么做。 我正在使用Angular,Asp.net,WebAPi和Oracle数据库。 提前致谢。 我的代码如下: ...

5 从函数返回值数组

我想用在我正在构建的自定义应用程序中使用的have_posts()函数来制作类似于WordPress的while函数。 我可能缺少一些简单的东西,但是我有一个数据库,其中包含一个名为clients的表。 客户端中有一些客户端信息,这些信息是通过我的函数client()从数据库中提取的。 ...

6 仅PHP数组返回值

我已经开始研究PHP面向对象的编程。 一般而言,我对PHP的经验有限。 我有如下PHP代码: “汽车”类别: 然后我试图输出此: 回声是: 但是我试图得到: foreach尝试产生了类似的响应。 我想了解我做错了什么。 ...

7 PHP,从数组返回值

我正在尝试从MySql表返回值,并且似乎能够获取除我所需的一切之外的所有内容! PHP: $ sql_fn给我正确的结果 $ row给我“数组” 但是$ data_fn没有给我任何东西。 本质上,我试图用这样的结果填充文本字段: HTML: 有人可以 ...

2013-10-20 16:25:18 4 73   php/ mysql
8 数组作为函数的返回值

有没有一种方法可以将返回的数组作为c ++中函数的结果? 这样,arr是一个局部变量,并且在函数返回后丢失了分配的内存块。 除了在功能块外定义数组之外,还有其他方法吗? ...

2013-11-13 12:43:49 5 153   c++
9 数组拒绝返回值

我正在尝试从Java中的persistencejs(这是一个库!)数据库中获取数据。 我正在获取值并将其推入数组中,我正在forEach循环中进行此操作。 在循环中,数组中填充了值,我已经使用警报确认了这一点。 但是当我在循环外查看数组时,它是空的。 为什么是这样? 这是代码( ...

10 返回值的数组公式

我一直在尝试使用VBA将数组公式添加到我的工作簿中,但是我无法使VBA输入的公式起作用。 如果我复制VBA输入的公式,则将其粘贴到右侧的下一个单元格中,然后按CTRL-SHIFT-ENTER然后按预期工作。 我什至尝试用使用宏记录器生成的那一行替换该行,但仍然遇到相同的问题。 另外,当 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM