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

时间:2013-04-11 12:10:07

标签: c# nhibernate nhibernate-mapping

据我所知,在NHibernate中,使用代码映射,我可以指定十进制属性的精度和比例,如下所示:

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

这很好,但我想知道是否有一种方法可以轻松地在所有类中轻松映射所有的小数属性。看起来有点疯狂,我必须通过我的所有映射并手动更新它们。有谁知道如何实现这一目标?

3 个答案:

答案 0 :(得分:4)

使用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中的约定集,除非您有其他具有不同比例或精度的小数。

答案 1 :(得分:3)

你可以写一个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);
    }
}

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

答案 2 :(得分:0)

您可以使用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);
    }
}

看起来你很容易适应映射所有小数,就像他用字符串一样。