views:

100

answers:

1

I am using a generic approach to receiving a single row from any Oracle table and displaying it in a datagridview, using the code below. But, if the table contains a column of float type and the value has a large number of decimal places, I get "Arithmetic operation resulted in an overflow" at the line: MyReader.GetValues(objCells);

            oCmd.CommandText = "OTCMIADM.OTCMI_GUI.GET_ROW";
            oCmd.CommandType = CommandType.StoredProcedure;
            oCmd.Parameters.Add("PI_TABLE_NAME", OracleDbType.Varchar2, 40).Value = cmbStagingTables.SelectedItem;
            oCmd.Parameters.Add("PI_ROWID", OracleDbType.Varchar2, 40).Value = txtRowID.Text;
            oCmd.Parameters.Add(new OracleParameter("PIO_CURSOR", OracleDbType.RefCursor)).Direction = ParameterDirection.Output;

            oCmd.ExecuteNonQuery();

            // clear the datagrid in preperation for loading
            dgvStagingTable.Columns.Clear();
            dgvStagingTable.Rows.Clear();

            using (OracleDataReader MyReader = oCmd.ExecuteReader())
            {
                int ColumnCount = MyReader.FieldCount;

                // add the column headers
                DataGridViewColumn[] columns = new DataGridViewColumn[ColumnCount];
                for (int i = 0; i < columns.Length; ++i)
                {
                    DataGridViewColumn column = new DataGridViewTextBoxColumn();
                    column.FillWeight = 1;
                    column.HeaderText = MyReader.GetName(i);
                    column.Name = MyReader.GetName(i);
                    columns[i] = column;
                }
                dgvStagingTable.Columns.AddRange(columns);

                // get the data and add the row
                while (MyReader.Read())
                {
                    //get all row values into an array
                    object[] objCells = new object[ColumnCount];
                    MyReader.GetValues(objCells);
                    //add array as a row to grid
                    dgvStagingTable.Rows.Add(objCells);
                }
            }

The stack trace shows: at Oracle.DataAccess.Types.DecimalConv.GetDecimal(IntPtr numCtx) at Oracle.DataAccess.Client.OracleDataReader.GetDecimal(Int32 i) at Oracle.DataAccess.Client.OracleDataReader.GetValue(Int32 i) at Oracle.DataAccess.Client.OracleDataReader.GetValues(Object[] values)

So I can see why it's causing an error (it's assuming a decimal conversion); but how do I get round this?

I tried explicitly setting the type of the column before loading the data with:

dgvStagingTable.Columns["TR_THROUGHPUT_TIME_NO"].ValueType = typeof(string);

and several other typeofs, but nothing made any difference.

Any help appreciated.

+1  A: 

I initially suggested using OracleDbTypeEx (http://download.oracle.com/docs/html/E15167_01/OracleParameterClass.htm#CHDJHDGE) to fix this for you, this was wrong so this is a new suggestion.

so what I did:

Create Table Testdecimalteable(
     Acol number(10) ,
     DecCol NUMBER(38,38)
);
/

Insert Into Testdecimalteable 
Select  level,Level/(power(2,level)) 
  From Dual
  Connect By Level < 100 ;

/

Create or replace Procedure Testprocdecimal(Crs OUT Sys_Refcursor)
AS
Begin
    Open Crs For
     Select * 
       FROM Testdecimalteable ;
END Testprocdecimal ;

Now this will get some data known to be beyond .net.

then the .net side:

    OracleConnection _conn = new OracleConnection("" );
    _conn.Open();
    OracleCommand oCmd = new OracleCommand();
    oCmd.CommandText = "Testprocdecimal";

    oCmd.CommandType = CommandType.StoredProcedure;
    oCmd.Connection = _conn;

    OracleParameter crs = new OracleParameter();
    crs.OracleDbType  = OracleDbType.RefCursor ;
    crs.Direction = ParameterDirection.Output;
    crs.ParameterName = "crs";
    oCmd.Parameters.Add(crs);
    using (OracleDataReader MyReader = oCmd.ExecuteReader())
    {
        int ColumnCount = MyReader.FieldCount;
        // get the data and add the row
        while (MyReader.Read())
        {
            //MyReader.GetOracleValue(1).ToString()
            Console.WriteLine(string.Format("{0}/{1}", MyReader.GetValue(0),MyReader.GetOracleValue(1).ToString()  ));


        }
    }

This converts everything to string but it'll work.

http://download-east.oracle.com/docs/html/A96160_01/features.htm#1048038

I just looked over your initial query once again, you are calling the query twice:

oCmd.ExecuteNonQuery();
...
using (OracleDataReader MyReader = oCmd.ExecuteReader())

you don't need the ExecuteNonQuery; the ExecuteReader executes the sp

tanging
Thanks for pointing out the query being called twice.And your propsed solution worked; I simply used the .GetOracleValue(i).ToString() to poulate the array before adding to the datagridview, works a treat!!Thanks again,D.
ValiantBoy