以相同的精度和比例映射所有小数

本文关键字:映射 小数 精度 | 更新日期: 2023-09-27 18:08:33

我知道在NHibernate中,使用代码映射,我可以像这样指定十进制属性的精度和比例:

Property(
    x => x.Dollars,
    m =>
        {
            m.Precision(9);
            m.Scale(6);
        }
 );

这很好,但我想知道是否有一种方法可以轻松地映射所有的十进制属性在所有类中以一种简单的方式。我必须遍历所有的映射并手动更新每个映射,这看起来有点疯狂。有谁知道这是怎么实现的吗?

以相同的精度和比例映射所有小数

在ModelMapper上使用BeforeMapProperty:-

var mapper = new ModelMapper();
mapper.BeforeMapProperty += (inspector, member, customizer) =>  {
    if (member.LocalMember.GetPropertyOrFieldType() == typeof (decimal))
    {
      customizer.Precision(9);
      customizer.Scale(6);
    }
};

唯一要添加的是删除所有出现的:-

 m => { m.Precision(9); m.Scale(6); }

将覆盖您在BeforeMapProperty中的约定设置,除非您有其他具有不同比例或精度的小数

你可以写一个UserType。这样做的好处是可以很容易地区分不同类型的小数(您很可能不希望对所有小数具有相同的精度)。

Property(
    x => x.Dollars,
    m => m.Type<MoneyUserType>()
 );

你花了一些功夫把它放到所有的货币属性中,但是你有一个更可读和自我描述的映射定义。


一个类似的解决方案(语法上),但更容易实现,是编写一个扩展方法来设置精度。

Property(
    x => x.Dollars,
    m => m.MapMoney()
 );
public static void MapMoney(this IPropertyMapper mapper)
{
    m.Precision(9);
    m.Scale(6);
}

这里也一样:它使映射定义更加自我描述。

(是的,我知道您不想更改所有的文件,但我仍然建议将这些信息放入映射文件中,因为它更明确地显示小数实际上是什么。更改所有Money属性的映射非常容易,但保留Amount属性。对于完全隐式的解决方案,请继续阅读


或者,您可以使用映射约定。这是非常强大的。您仍然可以覆盖映射文件中的精度,这提供了很大的灵活性。
mapper.BeforeMapProperty += MapperOnBeforeMapProperty;

private void MapperOnBeforeMapProperty(
    IModelInspector modelInspector,
    PropertyPath member,
    IPropertyMapper propertyCustomizer)
{
    Type propertyType;
    // requires some more condition to check if it is a property mapping or field mapping
    propertyType = (PropertyInfo)member.LocalMember.PropertyType;
    if (propertyType == typeof(decimal)) 
    {
        propertyCustomizer.Precision(9);
        propertyCustomizer.Scale(6);
    }
}

也可以将用户类型放入映射约定中,作为默认

可以使用FluentNHibernate吗?它使您能够根据需要灵活地应用约定。请参阅这里:https://github.com/jagregory/fluent-nhibernate/wiki/Conventions和这里:http://marcinobel.com/index.php/fluent-nhibernate-conventions-examples/,其中有这个特殊的例子:

public class StringColumnLengthConvention
    : IPropertyConvention, IPropertyConventionAcceptance
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Type == typeof(string))
            .Expect(x => x.Length == 0);
    }
 
    public void Apply(IPropertyInstance instance)
    {
        instance.Length(100);
    }
}

看起来你可以很容易地适应映射所有小数,就像他对字符串做的那样