【问题标题】:NHibernate decimal based UserType precision and scaleNHibernate 基于十进制的 UserType 精度和比例
【发布时间】:2012-02-02 13:15:34
【问题描述】:

我有一个自定义用户类型,用于将数据库中的十进制值映射到使用 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);
    }
}

【问题讨论】:

  • “动态变化”是什么意思?它不能动态更改,因为它会影响我们可能不想动态更改的数据库模式。还是我误会了你?
  • @NOtherDev 我希望能够在多个 ClassMap 中使用相同的类型,在一个中我可能想要使用 x & y 的比例和精度,在另一个中我可能想要使用 a & b .我已经更新了我的问题以反映这一点。

标签: sql-server nhibernate fluent-nhibernate


【解决方案1】:

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

更新:不幸的是我想不出一种方法来启用语法.CustomType&lt;SomeObject&gt;().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 参数化类型

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

【讨论】:

  • 我确实查看了 IParameterizedType 但没有看到它应该如何完成,也找不到任何示例。您能否使用上述组件展示一个示例,您提到如何使用 Ma(x => x.FieldName).CustomType().Scale(x).Precision(y); 设置比例和精度句法。谢谢
  • 感谢您的更新。我已经完成了第一个选项来让球滚动,但我会考虑你的其他建议,让你知道我的进展情况。谢谢
  • 我不得不让步,只是在用户类型中设置了精度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-17
  • 2015-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多