Vi è mai capitato "Arithmetic operation resulted in an overflow" nella lettura di campi numerici Oracle? Il problema si verifica in fase di lettura di una colonna NUMBER definita senza precisione; tale lettura potrebbe fallire.  La questione è ben descritta in "NHibernate Tales n°2 - Mapping Oracle NUMBER [Decimal]" dove il problema è poi inserito in un contesto in cui NHibernate è l'intermediario verso la base dati. Sebbene l'articolo è molto utile per capire la problematica non mi ha soddisfatto la soluzione poi applicata: l'uso dell'attributo "formula" per eseguire una TRUNC sullo specifico campo. Con tale soluzione si rinuncia alla funzionalità di update del campo. Infatti i campi in cui è si imposta l'attributo "formula" nel mapping sono considerati come campi calcolati e quindi non verranno considerati in fase di update; nella documentazione - parlando di tale attributo - si dice "Computed properties do not have a column mapping of their own" . 
Si è cercato di capire il problema alla radice... e se ne è ricavato un custom type (implementando IUserType). Usando NHibernate è nebuloso capire le ragione dell'errore in quanto nascosto tra i mille problemi del mapping. Se NON si usasse NHibernate ecco lo snippet di codice che segue potrebbe generare eccezione. 
// Arithmetic operation resulted in an overflow 
decimal value = reader.GetDecimal(ordinal); 
Il problema si risolve usando esplicitamente le librerie oracle; quindi una buona strategia a provider per l'accesso al dato evita IF e quanto ne consegue.
decimal value = 
((Oracle.DataAccess.Client.OracleDataReader)rs).GetOracleDecimal(ordinal);
implementando il custom type ecco una possibile implementazione del metodo NullSafeGet. 
public object NullSafeGet(IDataReader rs, string[] names, object owner) 
{ 
    int ordinal = rs.GetOrdinal(names[0]); 
    if (rs.IsDBNull(ordinal)) return new Decimal?(); 
    Oracle.DataAccess.Client.OracleDataReader oracle_dr = 
             (Oracle.DataAccess.Client.OracleDataReader)rs; 
    Decimal value = oracle_dr.GetOracleDecimal(ordinal); 
    return new Decimal?(value); 
}
ovviamente va poi inserito il nuovo tipo nella fase di mapping
<property 
    name="NomeProprietà" 
    column="NOME_COLONNA" 
    type="Esempio.OracleNumberType,Esempio"  /> 
 oO0( anche questa volta mi è sfuggita qualche peculiarità di NH? )
 
		
			posted @ giovedì 20 novembre 2008 00:12