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
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)
精彩评论