【问题标题】:First of Two Decimal Fields Causes Exception When Fetched获取时两个十进制字段中的第一个导致异常
【发布时间】:2020-04-23 20:42:44
【问题描述】:

我有一个用 C# 编写的应用程序,它使用 OdbcConnectionOdbcCommandOdbcDataReader。 该查询针对在 Linux 系统上运行的 Informix SE 数据库运行。

在查询中,在序数位置 27 和 28(索引 26 和 27),我尝试获取存储在每个水表记录中的纬度和经度。

这是 12K+ 帐户中第一个帐户的 lat/long,当使用 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。仅选择 lat/long decimal(15,10) 值,这些都可以完美获取。

这是我们 Linux 服务器上运行 SE 的 Informix 版本,对于 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 之前选择)是一个 smallint,我可以使用 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 ";                

【问题讨论】:

  • 你能检查dbReader.GetString(iReadIdx);的值吗?根据OdbcDataReader的源代码,数值和十进制类型的值首先被读取为字符串,然后使用Decimal.Parse转换为十进制
  • @OguzOzgul 按照你的建议做了。仍然抛出异常。无法将类型 Int32 转换为 String。
  • 您知道您使用的是哪个版本的 Informix ODBC 驱动程序吗?您知道您使用的是哪个版本的 Informix 服务器吗?这一切都是在 Windows 上运行的,还是你有一个基于 Unix 的 Informix 服务器(或者,也许是基于 Unix 的 C#)?

标签: c# odbc informix decimalformat


【解决方案1】:

我正在使用 .NET Framework 4.7 编译以下程序。

我使用 CSDK/ODBC 版本 4.50.FC3(Windows 64 位)在 Informix 数据库中尝试了以下简单程序,它运行良好。

您能否分享一下您正在使用的 Informix CSDK/ODBC 版本(“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 ****");
>    } 
>}

【讨论】:

  • 编辑 OP 以回答您的问题。
【解决方案2】:

您能否分享 System.Data.dll/System.Data.Odbc.dll 的版本(取决于您使用的框架版本,System.Data.Odbc.dll 可能是 System.Data.dll 本身的一部分) ?

另外,你能试试我分享的程序吗?这是自给自足的测试用例,这将确认问题,因为我们在各自的环境中尝试完全相同的测试用例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    相关资源
    最近更新 更多