Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FluentNHibernate mapping; Unable to map double or decimal with scale/precision

I'm working first time with FluentNHibernate, trying to map classes to SQL Express database. In general it works, but I'm unable to map Double or Decimal property types to specific scale/precision. Below shows result for a single property that I tested over and over with SchemaUpdate.Execute. In no case was I able to get it to work.

Would be really helpful to hear some explanation to the mappings that does not work as I expect (2-8)?

// Ok mappings:

1) Decimal: Map(Function(x) x.Balance) >> Decimal(19, 5)

// Mappings "errors":

2) Double: Map(Function(x) x.Balance).CustomSqlType("decimal") >> Decimal(18,0) - Why 0 precision is the default mapping here?

3) Double: Map(Function(x) x.Balance) >> Float , But; when running SchemaValidator after: HibernateException: Wrong column type in FnhDb.dbo.Account for column Balance. Found: float, Expected DOUBLE PRECISION

4) Decimal: Map(Function(x) x.Balance).Scale(9).Precision(2) >> SqlException: The scale (9) for column 'Balance' must be within the range 0 to 2.

5,6) Decimal or Double: Map(Function(x) x.Balance).Scale(9).Precision(2).CustomSqlType("numeric") >> numeric(18,0)

7,8) Decimal or Double: Map(Function(x) x.Balance).Scale(9).Precision(2).CustomSqlType("decimal") >> Decimal(18,0)


EDIT: I include code and hbm.xml (export) for case (4) here:

Public Class AccountMap
    Inherits ClassMap(Of Account)

    Public Sub New()
        MyBase.New()

        Id(Function(x) x.Id).GeneratedBy.Identity()
        Map(Function(x) x.Balance).Scale(9).Precision(2)   
        Map(Function(x) x.Deposits)
        Map(Function(x) x.WithDrawals)
    End Sub
End Class

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="false">
  <class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="RoboTrader.Account, RoboTrader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Account`">
    <id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Id" />
      <generator class="identity" />
    </id>
    <property name="Balance" type="System.Decimal, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Balance" precision="2" scale="9" />
    </property>
    <property name="Deposits" type="System.Nullable`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Deposits" />
    </property>
    <property name="WithDrawals" type="System.Nullable`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="WithDrawals" />
    </property>
  </class>
</hibernate-mapping>

EDIT2:

Btw, this is not a VB issue. I have the exact same problem in a C# project. Can it be the MsSql2008 configuration that is not compatible with Sql Express 2008 R2?


EDIT3:

Option Strict On

Imports System.Collections.Generic Imports System.Text Imports System

Public Class Account
    Public Sub New()
        MyBase.New()
End Sub

Private _Id As Integer

Private _Balance As Double

Private _Deposits As Integer

Private _WithDrawals As Integer


Public Overridable Property Id() As Integer
    Get
        Return _Id
    End Get
    Set(ByVal value As Integer)
        _Id = value
    End Set
End Property
Public Overridable Property Balance() As Double
    Get
        Return _Balance
    End Get
    Set(ByVal value As Double)
        _Balance = value
    End Set
End Property
Public Overridable Property Deposits() As Integer
    Get
        Return _Deposits
    End Get
    Set(ByVal value As Integer)
        _Deposits = value
    End Set
End Property
Public Overridable Property WithDrawals() As Integer
    Get
        Return _WithDrawals
    End Get
    Set(ByVal value As Integer)
        _WithDrawals = value
    End Set
End Property




End Class
like image 890
bretddog Avatar asked Jan 31 '11 00:01

bretddog


1 Answers

First of all, your understanding of Precision and Scale is wrong. Precision is always higher than Scale. See this MSDN documentation for a better understanding, which states:

Precision is the number of digits in a number. Scale is the number of digits to the right of the decimal point in a number. For example, the number 123.45 has a precision of 5 and a scale of 2.

In your second example, i.e. Decimal(18,0), 0 is Scale, not Precision. Precision is 18.

Secondly, your mapping should be this:

Map(Function(x) x.Balance).CustomSqlType("decimal").Precision(9).Scale(2);

If you set CustomSqlType("decimal") after setting Precision and Scale, the settings done by you will be reset.

EDIT:
You are using double in the declaration, where I think you should use decimal. See this question to know why. double is a floating type variable so it is mapped to a float by default until you mention otherwise or until the Precision is higher than 7. If you change the declaration of Balance to decimal, you can map the property like this without any problems:

Map(Function(x) x.Balance).Precision(9).Scale(2)
like image 126
Yogesh Avatar answered Nov 18 '22 11:11

Yogesh