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

C# Nhibernate:以相同的精度和比例映射所有小数,c#,nhibernate,nhibernate-mapping,C#,Nhibernate,Nhibernate Mapping,我知道在NHibernate中,使用代码映射,我可以指定十进制属性的精度和比例,如下所示: Property( x => x.Dollars, m => { m.Precision(9); m.Scale(6); } ); 这很好,但我想知道是否有一种方法可以轻松地映射所有类中的所有十进制属性。这似乎有点疯狂,我将不得不通过我所有的映射,并手动更新它们中的每一个。有人知道如何做到这一点

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

Property(
    x => x.Dollars,
    m =>
        {
            m.Precision(9);
            m.Scale(6);
        }
 );
这很好,但我想知道是否有一种方法可以轻松地映射所有类中的所有十进制属性。这似乎有点疯狂,我将不得不通过我所有的映射,并手动更新它们中的每一个。有人知道如何做到这一点吗?

你能使用吗?它使您能够根据需要灵活地应用约定。请参见此处:和此处:此处有此特定示例:

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);
    }
}
公共类StringColumnLength约定
:IPropertyConvention,IPropertyConvention验收
{
公共无效接受(IAcceptanceCriteria标准)
    {
criteria.Expect(x=>x.Type==typeof(string))
.Expect(x=>x.Length==0);
    }
 
公共无效应用(IPropertyInstance实例)
    {
例.长度(100);
    }
}

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

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

您可以编写
用户类型。优点是您可以轻松区分不同类型的小数(您很可能不希望所有小数都具有相同的精度)

这里也一样:它使映射定义更具自描述性

(是的,我知道您不想更改所有文件,但我仍然建议将此信息放入映射文件中,因为它更明确地表示小数点的实际含义。更改所有货币属性的映射非常容易,但保留金额属性。对于完全隐式的解决方案,请继续阅读。)


或者,您可以使用映射约定。这是非常强大的。您仍然可以覆盖映射文件中的精度,这提供了极大的灵活性

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);
    }
}

默认情况下,也可以将用户类型放入映射约定。

我不希望这样。映射了几十个类,只需重新映射我的小数就比切换到Fluent更容易了。谢谢。我给了里波分数是因为我读了他的第一篇,而且更简洁。我真的希望我能在这一点上投票两到三次,信息量很大。别担心,里波的回答被接受了,这也是他应得的,因为他实际上回答了这个问题(也比我快得多)。我提出了一些其他的建议,我很高兴你喜欢它…我以前从来没有想过第二个选项(扩展方法),但如果我说3+以上不同设置的类型,那会有所帮助。
Property(
    x => x.Dollars,
    m => m.MapMoney()
 );

public static void MapMoney(this IPropertyMapper mapper)
{
    m.Precision(9);
    m.Scale(6);
}
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);
    }
}