索引超出了OracleUdt.SetValue()中数组的范围 [英] Index is out of bounds of the array in OracleUdt.SetValue()

查看:149
本文介绍了索引超出了OracleUdt.SetValue()中数组的范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要更好的眼睛,我已经打了好几天了。



我有很多类可以将Oracle UDT传递给包中的程序。它们都有效,包括几个与给我配合的几乎相同的几个。但是这个在调用OracleUdt.SetValue()时返回Index is out of bounds ..错误。



绝对最小代码在下面,它是一个嘴巴-充分。道歉。



--- Oracle类型--- <前lang =Javascript>创建或替换类型DMA_NUM_Varray IS数字的VARRAY( 250 );





---在Oracle软件包中---



程序Create_commercials_Owr(f_dma_num_tab IN DMA_NUM_Varray)IS ... 





此过程实际上有4个其他参数,包括2个UDT,所有参数都在参数列表之前定义。其中一个是另一个VArray(50),并且没有返回错误,但只返回DMANumberArray。



--- C#.NET - -



  public   class  DMANumberArray:INullable,IOracleCustomType {

[OracleArrayMapping()]
public OracleDecimal [ ]数组;

private bool isNull;
private OracleUdtStatus [] statusArray;

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

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

public static DMANumberArray NULL {
get {
DMANumberArray did = new DMANumberArray();
did.isNull = true ;
返回;
}
}

public virtual void FromCustomObject(OracleConnection oracleConn, IntPtr udt){
OracleUdt.SetValue(oracleConn,udt, 0 ,Array,statusArray); // ***错误发生在这里***
}

public virtual void ToCustomObject(OracleConnection) oracleConn, IntPtr udt){
object objectStatusArray = ;
Array =(OracleDecimal [])OracleUdt.GetValue(oracleConn,udt, 0 out objectStatusArray);
statusArray =(OracleUdtStatus [])objectStatusArray;
}

}

[OracleCustomTypeMapping( APCTS.DMA_NUM_VARRAY)]
public class DMANumberArrayFactory:IOracleCustomTypeFactory,IOracleArrayTypeFactory {

public IOracleCustomType CreateObject(){
return new DMANumberArray();
}
public 数组CreateArray( int elementCount){
< span class =code-keyword> return
new OracleDecimal [elementCount];
}
public 数组CreateStatusArray( int elementCount){
< span class =code-keyword> return
new OracleUdtStatus [elementCount];
}
}

DataTable dmaTable = new DataTable();
使用(SqlDataAdapter da = new SqlDataAdapter(query,sql)){
da.Fill(dmaTable);
}
DMANumberArray dma = new DMANumberArray();
idCount = dmaTable.Rows.Count;
如果(idCount > 250 )idCount = 250 ; // 即使我将此值更改为5或1 ***也会发生错误更正:它适用于值到4,但不是> = 5
dma.Array = new OracleDecimal [idCount]; // limit 250
for int i = 0 ; i < idCount; i ++){
dma.Array [i] = OracleDecimal.Parse(dmaTable.Rows [i] [ DMA_Number]的ToString());
}
dma.StatusArray = new OracleUdtStatus [] {OracleUdtStatus.NotNull,OracleUdtStatus.Null,OracleUdtStatus.NotNull,OracleUdtStatus.NotNull};

string query = APCTS.OWR_APIS.Create_commercials_Owr;
com.Connection = oracle;
使用(OracleCommand cmd = new OracleCommand(query,oracle)){
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter paramDMAArrayObject = new OracleParameter();
paramDMAArrayObject.OracleDbType = OracleDbType.Array;
paramDMAArrayObject.Direction = ParameterDirection.Input;
paramDMAArrayObject.UdtTypeName = APCTS.DMA_NUM_VARRAY;
paramDMAArrayObject.Value = dma;

cmd.Parameters.Add(paramDMAArrayObject);
cmd.ExecuteNonQuery();
}





我不能在我的生活中看到有什么东西索引大于数组的东西,因为它的大小,并限制为250个元素。我看到的一件奇怪的事情是在类DMANumberArrayFactory中,特别是在CreateArray中。当我在这里打破时,elementCount的值总是为零,即使UDT对象的数组创建的值大于零。



我错过了什么?

解决方案

最后想出来了。我专注于错误的阵列。事实证明,状态数组需要重新调整大小以匹配VArray的大小。来自Oracle的愚蠢,不完整,模糊(非)的文档,并没有真正解释这是什么或如何使用它。



没有这样的解释,我只是使用了和Oraale的示例代码相同的东西,它传递了四个元素。



 dma.StatusArray = new OracleUdtStatus [] {OracleUdtStatus.NotNull,OracleUdtStatus.Null,OracleUdtStatus.NotNull,OracleUdtStatus.NotNull}; 





但是你用它来标记VArray中的每个元素为null或not-null。如果您的VArray有250个元素,则使用250个元素定义状态数组,然后使用OracleUdtStatus.Null或OracleUdtStatus.NotNull填充每个元素。这对我来说似乎疯了 - 没用。似乎转换器应该能够弄清楚自己发送的元素是否为空。但是,文档和样本并没有告诉你它为什么需要它。


I need better eyes on this, I've been beating mine over it for days now.

I have a lot of classes built to pass Oracle UDTs to a procedure in a package. They all work, including several that are nearly identical to the one giving me fits. But this one returns the "Index is out of bounds.." error in calling OracleUdt.SetValue().

The absolute minimum code is below, and it's a mouth-full. Apologies for the length.

--- Oracle Types ---

create or replace type DMA_NUM_Varray IS VARRAY(250) OF NUMBER;



--- In an Oracle Package ---

PROCEDURE Create_commercials_Owr(f_dma_num_tab IN DMA_NUM_Varray) IS ...



This procedure actually has 4 other parameters, including 2 UDTs, all defined before this one on the parameter list. One of these is another VArray(50), and no error is returned on it, but only on the DMANumberArray.

--- C# .NET ---

public class DMANumberArray : INullable, IOracleCustomType {

	[OracleArrayMapping()]
	public OracleDecimal[] Array;

	private bool isNull;
	private OracleUdtStatus[] statusArray;

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

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

	public static DMANumberArray NULL {
		get {
			DMANumberArray did = new DMANumberArray();
			did.isNull = true;
			return did;
		}
	}

	public virtual void FromCustomObject(OracleConnection oracleConn, IntPtr udt) {
		OracleUdt.SetValue(oracleConn, udt, 0, Array, statusArray); // *** Error happens here ***
	}

	public virtual void ToCustomObject(OracleConnection oracleConn, IntPtr udt) {
		object objectStatusArray = null;
		Array = (OracleDecimal[])OracleUdt.GetValue(oracleConn, udt, 0, out objectStatusArray);
		statusArray = (OracleUdtStatus[])objectStatusArray;
	}

}

[OracleCustomTypeMapping("APCTS.DMA_NUM_VARRAY")]
public class DMANumberArrayFactory : IOracleCustomTypeFactory, IOracleArrayTypeFactory {

	public IOracleCustomType CreateObject() {
		return new DMANumberArray();
	}
	public Array CreateArray(int elementCount) {
		return new OracleDecimal[elementCount];
	}
	public Array CreateStatusArray(int elementCount) {
		return new OracleUdtStatus[elementCount];
	}
}

DataTable dmaTable = new DataTable();
using (SqlDataAdapter da = new SqlDataAdapter(query, sql)) {
	da.Fill(dmaTable);
}
DMANumberArray dma = new DMANumberArray();
idCount = dmaTable.Rows.Count;
if (idCount > 250) idCount = 250; // The error occurs even if I change this value to 5, or 1 *** Correction: it works for values up to 4, but not >= 5
dma.Array = new OracleDecimal[idCount]; //limit 250
for (int i = 0; i < idCount; i++) {
	dma.Array[i] = OracleDecimal.Parse(dmaTable.Rows[i]["DMA_Number"].ToString());
}
dma.StatusArray = new OracleUdtStatus[] { OracleUdtStatus.NotNull, OracleUdtStatus.Null, OracleUdtStatus.NotNull, OracleUdtStatus.NotNull };

string query = "APCTS.OWR_APIS.Create_commercials_Owr";
com.Connection = oracle;
using (OracleCommand cmd = new OracleCommand(query, oracle)) {
	cmd.CommandType = CommandType.StoredProcedure;
	OracleParameter paramDMAArrayObject = new OracleParameter();
	paramDMAArrayObject.OracleDbType = OracleDbType.Array;
	paramDMAArrayObject.Direction = ParameterDirection.Input;
	paramDMAArrayObject.UdtTypeName = "APCTS.DMA_NUM_VARRAY";
	paramDMAArrayObject.Value = dma;

	cmd.Parameters.Add(paramDMAArrayObject);
	cmd.ExecuteNonQuery();
}



I cannot for the life of me see where anything is indexing something larger than the array as it was sized, and limited to 250 elements. The one odd thing I do see is in class DMANumberArrayFactory, specifically in CreateArray. When I break here, the value of elementCount is always zero, even when the UDT object's Array was created with values greater than zero.

What have I missed?

解决方案

Finally figured this out. I was focusing on the wrong array. Turns out it was the status array that needed to be re-sized to match the size of the VArray. Dumb, incomplete, vague (non)documentation from Oracle, doesn't really explain what this is for or how to use it.

Not having such explanation, I just used the same thing as in Oraale's sample code, which was passing four elements.

dma.StatusArray = new OracleUdtStatus[] { OracleUdtStatus.NotNull, OracleUdtStatus.Null, OracleUdtStatus.NotNull, OracleUdtStatus.NotNull };



But you use it to flag each and every element in your VArray as either null or not-null. If your VArray has 250 elements, you define the status array with 250 elements, and then you populate each element with OracleUdtStatus.Null or OracleUdtStatus.NotNull. That seems crazy-useless to me. Seems like the converter should be able to figure out itself whether an element you're sending is null or not. But then, the documentation and samples do not tell you why it needs this.


这篇关于索引超出了OracleUdt.SetValue()中数组的范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆