Точность и масштабирование пользовательского типа на основе десятичных чисел NHibernate - PullRequest
2 голосов
/ 02 февраля 2012

У меня есть пользовательский тип пользователя, который используется для сопоставления десятичного значения из базы данных со свойством объекта, используя 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 Ответ

2 голосов
/ 06 февраля 2012

вы можете реализовать 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 параметризованного типа

<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 }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...