我有一个用C#编写的应用程序,它使用了 OdbcConnection, OdbcCommand和 OdbcDataReader. 查询是在Linux系统上运行的Informix SE数据库中进行的。
在查询中,在序数位置27和28(索引26和27),我试图获取每个水表记录中存储的经纬度。
下面是12K+账户中第一个账户的latlong,当使用dbReader.GetDecimal()读取时,第一个值以无效投递异常失败。
geo_lat geo_lon
42.4236953219 -71.1752100161
第一个被获取的字段是GetDecimal(26),它抛出了一个无效的投递异常。
// Type x = dbReader.GetFieldType(iReadIdx); after
// testing, it's found to be a decimal.
decimal x = dbReader.GetDecimal(iReadIdx);
retStr = x.ToString();
请注意,注释出来的代码是为了确定索引26真的是十进制而运行的。我确实考虑过是不是序数出错了。他们没有。
我唯一能看到的是纬度是正数,而经度是负数。
如果有必要,我可以临时编个表,映射出一个字符串版的纬度,反正我想要的就是字符串中的纬度。
有什么办法可以进一步调试这个问题,希望能得到大家的帮助。
回答评论的问题。
我试过下面的方法,会产生异常。
decimal x = decimal.Parse(dbReader.GetString(iReadIdx));
但这个没有,但也没有读出完整的小数值。
decimal x = decimal.Parse(dbReader.GetInt32(iReadIdx).ToString());
retStr = x.ToString();
break;
如果负值没有正确获取,我会理解,但正值没有正确获取。
然而,第二次调用使用将其作为字符串读取失败。我必须想出一些笨拙的办法.回答最近提出的问题。
我的解决方法是写了一个单独的查询,使用与主查询相同的OdbcConnection。只选择latlong十进制(15,10)的值,这些值就能完美地获取。
这是我们Linux服务器上的Informix版本,它运行的是SE,Informix SE的变化不大。
[ics@steamboy ics_client]$ esql -V
IBM Informix CSDK Version 3.00, IBM Informix-ESQL Version 3.00.UC3DE
Software Serial Number AAA#B000000
[ics@steamboy ics_client]$
这里是主选择,包含字段geo_lat和geo_lon。是geo_lat的GetDecimal(26)抛出了一个无效的投递异常。请注意 folio (选择在 geo_lat 之前)是个 小企业,我可以用这个方法只读出整数部分 GetInt32(26).
string meterQ =
"select m.acct_no, " + //1
" m.suffix, " + //2
" m.reg_no, " + //3
" w.service, " + //4
" m.property_type, " + //5
" w.mtr_addr_no, " + //6
" w.mtr_addr_str, " + //7
" w.mtr_addr_apt, " + //8
" w.owner_city, " + //9
" w.owner_state, " + //10
" w.owner_zip, " + //11
" w.owner_name_1, " + //12
" w.owner_name_2, " + //13
" w.owner_addr_1, " + //14
" w.owner_addr_2, " + //15
" w.re_acct, " + //16
" m.meter_type, " + //17
" m.meter_num, " + //18
" m.date_installed, " + //19
" m.numdigits, " + //20
" w.billed_or_not, " + //21
" m.meter_size, " + //22
" m.arb_no, " + //23
" m.read_instr, " + //24
" m.book, " + //25
" m.folio, " + //26
" m.geo_lat, " + //27
" m.geo_lon, " + //28
// cmn 4/24/2020 lat Lon fetched by separate query.
" m.devicetype, " + //29
" m.channel, " + //30
" w.same_re_addr " + //31
"from water w , meter m " +
"where w.acct_no = m.acct_no " +
"and m.last_update >= '" + cutoffDateP + "' " +
"and m.meter_type != 'FS' " +
"and w.last_update is not null " +
"order by m.acct_no asc, m.suffix asc ";
我使用.NET Framework 4.7来编译下面的程序。
我使用CSDKODBC 4.50.FC3版本(Windows 64-bit)在Informix数据库中尝试了下面的简单程序,它工作得很完美。
你能不能也分享一下你使用的Informix CSDKODBC的版本("esql -V "的输出)?
下面程序的输出如下。
**** Starting of Decimal Testcase ****
**** Connected ****
create temp table mytable (intcol int, deccol1 decimal(20,10), deccol2 decimal(20,10));
Table mytable created
insert into mytable values(1,'42.4236953219', '-71.1752100161');
INSERT 1 rows
select * from mytable;
intcol = 1
deccol1 = 42.4236953219
deccol2 = -71.1752100161
**** End of Decimal Testcase ****
Program:
--------
>using System;
>using System.Data;
>using System.Data.Odbc;
>using System.Text;
>
>public class OdbcDecimal
>{
> static void Main(string[] args)
> {
> int insrow = 0;
> try
> {
> string connectionString = "DSN=InformixDSN";
>
> try
> {
> Console.WriteLine(" **** Starting of Decimal Testcase ****");
> using (OdbcConnection conn0 = new OdbcConnection(connectionString))
> {
> conn0.Open();
> Console.WriteLine(" **** Connected ****");
> using (OdbcCommand cmd0 = conn0.CreateCommand())
> {
> try
> {
> cmd0.CommandText = "drop table mytable;";
> //Console.WriteLine(cmd0.CommandText);
> cmd0.ExecuteNonQuery();
> //Console.WriteLine(" Table mytable dropped");
> }
> catch { }
>
> cmd0.CommandText = "create table mytable (intcol int, deccol1 >decimal(20,10), deccol2 decimal(20,10));";
> Console.WriteLine(cmd0.CommandText);
> cmd0.ExecuteNonQuery();
> Console.WriteLine(" Table mytable created");
>
> cmd0.CommandText = "insert into mytable values(1,'42.4236953219', >'-71.1752100161');";
> Console.WriteLine(cmd0.CommandText);
> insrow = cmd0.ExecuteNonQuery();
> Console.WriteLine(" INSERT " + insrow + " rows");
>
> cmd0.CommandText = "select * from mytable;";
> Console.WriteLine(cmd0.CommandText);
>
> OdbcDataReader dr = null;
> Int32 vid = 0;
> decimal x;
> decimal y;
>
> dr = cmd0.ExecuteReader();
> while (dr.Read())
> {
> try
> {
> if (!dr.IsDBNull(0))
> {
> vid = dr.GetInt32(0);
> Console.WriteLine("intcol = " + vid + " ");
> }
> else
> {
> Console.WriteLine("intcol = null ");
> }
>
> if (!dr.IsDBNull(1))
> {
> x = dr.GetDecimal(1);
> Console.WriteLine("deccol1 = " + x.ToString() + " ");
> }
> else
> {
> Console.WriteLine("deccol1 = null ");
> }
>
> if (!dr.IsDBNull(2))
> {
> y = dr.GetDecimal(2);
> Console.WriteLine("deccol2 = " + y.ToString() + " ");
> }
> else
> {
> Console.WriteLine("deccol2 = null ");
> }
> }
> catch (OverflowException exc)
> {
> Console.WriteLine(exc.Message);
> }
> }
> dr.Close();
>
> }
> }
> }
> catch (OdbcException ioe)
> {
> Console.WriteLine(ioe.Message);
> Console.WriteLine(ioe.StackTrace);
> }
> }
> catch (Exception ex)
> {
> Console.WriteLine(ex.Message);
> Console.WriteLine(ex.StackTrace);
> }
> Console.WriteLine(" **** End of Decimal Testcase ****");
> }
>}
你能分享System.Data.dllSystem.Data.Odbc.dll的版本吗(根据你使用的Framework版本,System.Data.Odbc.dll可能是System.Data.dll本身的一部分)?
另外,你可以试试我分享的程序吗?这是一个自足的测试案例,这将确认问题,因为我们在各自的环境中尝试完全相同的测试案例。