2016-02-05 6 views
8

Nel mio codice stavo usando System.Data.OracleClient per ora connessione al database. Vorrei sostituire questa libreria (perché è obsoleta) con Oracle.DataAccess. Purtroppo ho trovato che DataRow.Field() genera InvalidCastException. Lo stesso comportamento è con (decimal)x.Rows[0]["COLUME_NAME"]. Non ho questo problema con System.Data.OracleClient.Oracle.DataAccess DataRow.Field <decimal> InvalidCastException

Ecco esempio di codice

using (var oracleConnection = new OracleConnection(connectionString)) 
{ 
    using (var command = new OracleCommand("select * from tr", oracleConnection)) 
    { 
     var result = new DataTable(); 
     var adapter = new OracleDataAdapter(command); 
     adapter.Fill(result); 
     Console.WriteLine(result.Rows[0].Field<decimal>("TR_SEQ_NUM")); 
     //Console.WriteLine((decimal)result.Rows[0]["TR_SEQ_NUM"]); 
    } 
} 

TR_SEQ_NUM ha NUMBER(8,0) tipo di dati e la piena eccezione è:

System.InvalidCastException: Specified cast is not valid. 
    at System.Data.DataRowExtensions.UnboxT`1.ValueField(Object value) 

Codice esempio lavorare con System.Data.OracleClient ma non con Oracle.DataAccess

So che posso usare Convert.ChangeType ma mi chiedo se c'è un modo per avere lo stesso comportamento come con System.Data.OracleClient. Refactoring di tutto il mio codice sarà troppo costoso.

+0

utilizzando Oracle.ManagedDataAccess.Client; // usa la versione gestita Cosa succede quando chiami tbl.Rows [0] [0] .GetType(); ? . Campo non è possibile nella nuova versione si utilizzano indici/nomi delle colonne. Dovrai refactoring, System.Data.OracleClient è scaduto, ma il casting dovrebbe essere gestito per te quando compili la tabella ... – Matt

+0

Inoltre, Number (8,0) non sarebbe un decimale, perché lo stai trasmettendo a uno? È molto raro che sia necessario utilizzare Decimal, non che causi il problema che si sta verificando ma che potrebbe far risparmiare memoria quando l'app è in esecuzione – Matt

+0

Sono d'accordo con _LessNoviceProgrammer_. Penso che il tipo corretto per 'NUMBER (8,0)' sia 'int' ... –

risposta

1

Il valore nel database non è un decimale e un int incatenato (il parametro "valore" nel messaggio di errore) non può essere convertito in un decimale, nonostante il cast di un int con un decimale sia OK. This answer leads to more info.

Potete vederlo in azione con questa:

void Main() 
{ 
    int anInt = 5; 
    object boxedInt = (object)anInt; 
    decimal unboxed = Convert.ToDecimal(boxedInt); //5 
    decimal unboxed2 = (decimal)boxedInt; //InvalidCastException 
} 

Se si guarda il metodo Unbox.ValueField, lo fa ...

private static T ValueField(object value) 
    { 
    if (DBNull.Value == value) 
     throw DataSetUtil.InvalidCast(Strings.DataSetLinq_NonNullableCast((object) typeof (T).ToString())); 
    return (T) value; 
    } 

In pratica avrete bisogno di

Convert.ToDecimal(rows[0]["TR_SEQ_NUM"]); 
0

Sembra che i dati contengano valori nulli e non è possibile convertire un dato nullable in un tipo decimale non annullabile

Utilizza lo statment qui sotto per leggere la colonna decimale annullabile da DB

result.Rows[0].Field<decimal?>("TR_SEQ_NUM")