问题描述
我在Windows XP x64机器上使用VS 2008和.Net 2.0,我正在使用10g 10.1.0.2.0服务器上的Oracle数据库。
该项目最初编写与MS SQL一起工作,但我们希望将其扩展为包含Oracle。我们有一个带有ntext行的表,用于存储一些XML,在Oracle中转换为Clob。
一开始,用MS SQL读取数据的原始函数似乎工作正常,但是当我们检查结果时,它们已被破坏。一点调查显示,GetChars实际上只将结果的一半写入char数组。如果我们给它一个1000的长度,则返回值为1000,但只更新1000个字符数组中的前500个字符。我们尝试更改请求的长度,返回值始终等于长度,但写入的字节数是我们要求的一半。作为测试我尝试将实际缓冲区保留为1000个字符,但告诉它检索两倍的字符,并成功检索到22801个字符的前21000个。但是,当它试图检索最后一组2000个字符时,返回值仅为1801,正如预期的那样,但只更新了char数组的前900个字符。如果我更改代码只保存那900个字符,然后使用GetChars进行另一个检索,它返回值901,但只更新数组中的前450个字符。我很确定我可以继续检索每个循环中剩余数据的一半,直到它变为单个字节,但这显然不是一个理想的解决方案。
Oracle db中的Clob有一个我们的测试用例中的长度为22801(使用dbms_lob.getlength检查),MS SQL版本中的等效ntext行的长度为45648(使用datalength检查),因此MS SQL似乎使用宽字符而Oracle不是。 (这两组XML实际上是相同的,但是MS SQL的名称有点长,因此略有不同。)然而,OracleDataReader.GetChars上的MSDN页面没有说明必须考虑广泛与非广泛的角色或人们将如何这样做。
所以有人知道问题是什么或如何解决它?循环的代码包含在下面。谢谢!
使用(DbDataReader reader = cmd.ExecuteReader())
{
if if(reader.Read())
{
int startIndex = 0;
long retval = 0;
int bufferSize = 1000;
char [] outByte = new char [bufferSize];
StringWriter writer = new StringWriter();
retval = reader.GetChars(0,startIndex,outByte,0,bufferSize);
//继续存在超出缓冲区大小的字节。
while(retval == bufferSize) ){
writer.Write(outByte);
writer.Flush();
//将起始索引重新定位到最后一个缓冲区的末尾并填充缓冲区。
startIndex + = bufferSize;
retval = reader.GetChars(0,startIndex,outByte,0,bufferSize);
//写出剩余的缓冲区。 .Write(outByte,0,(int)retval);
writer.Flush();
//关闭输出文件。作者.Close();
return writer.ToString();
}
用于oracle版本的SQL代码是"select xml_c"来自xml_table的ode,其中id =:p_id",虽然这似乎工作正常,因为我们没有收到任何错误,但我们只丢失了一半来自GetChars的数据。
在OracleDataReader上的MSDN页面。 GetChars - http://msdn.microsoft.com/en-us/library/system.data.oracleclient.oracledatareader.getchars.aspx
I'm using VS 2008 and .Net 2.0 on Windows XP x64 machine, and i'm talking to an Oracle database on a 10g 10.1.0.2.0 server.
The project was originally written to work with MS SQL, but we want to expand it to include Oracle. We have a table with a ntext row, used to store some XML, that got converted to a Clob in Oracle.
At first it seemed that the original function for reading that data with MS SQL was working fine, but when we checked the results they were corrupted. A little investigation revealed that GetChars was actually only writing half the results to the char array. If we give it a length of 1000 the return value is 1000, but only the first 500 characters in the 1000 character array are updated. We tried changing the length requested and the return value is always equal to the length but the number of bytes written is half what we asked for. As a test i tried leaving the actual buffer at 1000 characters but telling it to retrieve twice as many characters, and it successfully retrieved the first 21000 of 22801 characters. However when it tried to retrieve the last set of 2000 characters the return value was only 1801, as expected, but only the first 900 characters of the char array were updated. If i change the code to save just those 900 characters and then do another retrieve with GetChars it returns a value of 901, but only updates the first 450 characters in the array. I'm pretty sure i could continue retrieving half the remaining data with each loop until it got down to a single byte, but that is obviously not an ideal solution.
The Clob in the Oracle db has a length of 22801 in our test case (checked using dbms_lob.getlength,) and the equivalent ntext row in the MS SQL version has a length of 45648 (checked using datalength) so it seems that MS SQL is using wide characters and Oracle isn't. (The two sets of XML are virtually identical, but the MS SQL one has a somewhat longer name, hence the slight difference.) However the MSDN page on OracleDataReader.GetChars doesn't say anything about having to account for wide vs. non-wide chars or how one would go about doing so.
So does anyone know for sure what the problem is or how to fix it? The code for the loop is included below. Thanks!
using (DbDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
int startIndex = 0;
long retval = 0;
int bufferSize = 1000;
char[] outByte = new char[bufferSize];
StringWriter writer = new StringWriter();
retval = reader.GetChars(0, startIndex, outByte, 0, bufferSize);
// Continue while there are bytes beyond the size of the buffer.
while (retval == bufferSize)
{
writer.Write(outByte);
writer.Flush();
// Reposition start index to end of last buffer and fill buffer.
startIndex += bufferSize;
retval = reader.GetChars(0, startIndex, outByte, 0, bufferSize);
}
// Write the remaining buffer.
writer.Write(outByte, 0, (int)retval);
writer.Flush();
// Close the output file.
writer.Close();
return writer.ToString();
}
}
The SQL code for the oracle version is "select xml_code from xml_table where id = :p_id", though that seems to be working fine since we're not getting any errors, we're only losing half the data from GetChars.
MSDN page on OracleDataReader.GetChars - http://msdn.microsoft.com/en-us/library/system.data.oracleclient.oracledatareader.getchars.aspx
推荐答案
这篇关于OracleDataReader.GetChars只返回Clob中一半的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!