Search code examples
.netnhibernatesql-server-2012bigdecimal

.NET, SQL Server, NHibernate and high-precision decimals


I need to use decimal values with high precision - for instance, SQL Server 2012 allows for up to 38 digits.

This is more precision than what System.Decimal supports (28-29 significant digits).

Let's assume I use a certain implementation of BigDecimal to represent this on the CLR side that supports any needed constructor (e.g. from a string representation of the number).

The values are stored in the SQL Server database using the appropriate SQL Server decimal type.

I'm using NHibernate for ORM. I'm trying to create an IUserType implementation that converts from the DB representation to the BigDecimal representation.

My problem is, I can't figure out how to do this without the use of an intermediate System.Decimal which would truncate data.

public virtual object NullSafeGet(IDataReader rs, string[] names, object owner)
{
    // ??
    object objValue = NHibernateUtil.Decimal.NullSafeGet(rs, names[0]);
    //objValue is already a System.Decimal

    if (!Convert.IsDBNull(objValue))
    {
        return new BigDecimal(objValue.ToString());
    }
    return null;
}

Update: 

In the Java counterpart, I can see a special Hibernate DbType for this exact use case: org.hibernate.type.BigDecimalType

I'm starting to wonder if this is a limitation of the underlying ADO.NET layer - it also has no defined DbType appropriate for m use case, as far as I can tell.


Solution

  • There is no need to call NHibernateUtil.Decimal.NullSafeGet(). Instead you should use methods available on the IDataReader to get the value.

    If you use e.g. GetValue() on the reader, by the type mapping table it looks like you will get an instance of System.Data.SqlTypes.SqlDecimal.

    Then you will have to figure out how to convert the value to your BigDecimal.