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