7

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

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

这很好,但我想知道是否有一种方法可以轻松地映射所有类中的所有小数属性。我必须遍历所有映射并手动更新每个映射,这似乎有点疯狂。有谁知道如何做到这一点?

4

3 回答 3

4

BeforeMapProperty在 ModelMapper 上使用:-

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除非您有其他具有不同比例或精度的小数。

于 2013-04-11T12:25:50.540 回答
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);
    }
}

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

于 2013-04-11T12:26:04.420 回答
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);
    }
}

这看起来您可以轻松地适应映射所有小数,就像他对字符串所做的那样。

于 2013-04-11T12:20:51.097 回答