基于NHibernate十进制的UserType精度和比例

时间:2012-02-02 13:15:35

标签: sql-server nhibernate fluent-nhibernate

我有一个自定义用户类型,用于使用Fluent NHibernate从数据库中的十进制值映射到实体上的属性。对象的映射工作正常,但我不知道如何动态更改十进制sql数据类型的精度和比例,以便我可以在不同的类映射中使用不同的精度和比例。

以下是我的自定义类型的示例;

public struct MyCustomType
{
    private readonly decimal value;

    public MyCustomType(decimal value)
    {
        this.value = value;
    }

    public static implicit operator MyCustomType(decimal value)
    {
        return new MyCustomType(value);
    }

    public static implicit operator decimal(MyCustomType value)
    {
        return value.value;
    }

    public string ToString(string format, IFormatProvider provider)
    {
        return value.ToString(format, provider);
    }
}

这就是我在做用户类型的方式。

public class MyCustomUserType : IUserType
{
    ...

    public object NullSafeGet(IDataReader rs, string[] names, object owner)
    {
        MyCustomType customType = (decimal)rs[names[0]];

        return customType;
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index)
    {
        var parameter = (IDataParameter)cmd.Parameters[index];
        parameter.Value = (decimal)(MyCustomType)value;
    }

    ...

    public SqlType[] SqlTypes
    {
        //I think I could hard code the precision and scale here
        get { return new[] { SqlTypeFactory.Decimal }; }
    }

    public Type ReturnedType
    {
        get { return typeof(MyCustomType); }
    }

    public bool IsMutable
    {
        get { return true; }
    }
}

最后这就是我映射对象的方式

public class SomeObjectMappingBase: ClassMap<SomeObject>
{
    protected SomeObjectMappingBase()
    {
        //Currently I do this
        Map(x => x.CustomTypeField).CustomType<MyCustomUserType>();
        //I would like to be able to do this but it does not work
        Map(x => x.CustomTypeField).CustomType<MyCustomUserType>().Scale(10).Precision(20);
    }
}

1 个答案:

答案 0 :(得分:2)

您可以为每个精度和比例组合实现IParameterizedUserType或子类MyCustomUserType。

更新:不幸的是,我想不出一种启用语法.CustomType<SomeObject>().Scale(x).Precision(y)的方法。代替

选项1到子类

class MyCustomUserTypeFor10And20 : MyCustomUserType
{
    public override SqlType[] SqlTypes
    {
        get { return new[] { SqlTypeFactory.GetDecimal(10, 20) }; }
    }
}


Map(x => x.CustomTypeField).CustomType<MyCustomUserTypeFor10And20>();

选项2 parameterizedType

<property name="CustomProperty">
   <type name="MyCustomUserType">
      <param name="precision">10</param>
      <param name="scale">20</param>
   </type>
</property>

class MyCustomUserType : IParameterizedType
{
    public void SetParameterValues(IDictionary<string, string> parameters)
    {
        precision = parameter["precision"];
        scale = parameter["scale"];
    }
}

选项3以某种方式使用它:不要映射自定义类型,但在配置

上设置它
var mapping = config.GetClassMapping(typeof(...));

foreach (var prop in mapping.PropertyIterator.Where(p => p.Type.ReturnedClass == typeof(decimal)))
{
    prop.Type = new CustomType(typeof(MyCustomType), new Dictionary<string, string>
    {
        { "precision", prop.Type.SqlTypes(null)[0].Precision },
        { "scale", prop.Type.SqlTypes(null)[0].Precision }
    });
}