можно ли использовать функции ввода манифеста sqlite в nhibernate?

StackOverflow https://stackoverflow.com/questions/1213728

Вопрос

это было опубликовано на hibernate.org форумах и в списке пользователей без особой удачи, поэтому я решил попробовать здесь.

Проще говоря, предположим, у меня есть класс:

class A
{
   public virtual object SomeValue { get; set; }
}

тип someValue в основном находится в наборе конвертируемых типов .NET ICON (примитивы, такие как bool, byte, char, int16, double, float и т.д.), Плюс byte[] и string .

Я пытаюсь создать отображение nhibernate для A, чтобы отразить это - чтобы я мог в принципе установить someValue для произвольного объекта (одного из приведенных выше типов) и извлечь его позже.Затем мой applogic поразмыслит над этим, чтобы найти нужный тип и вести себя соответствующим образом.

До сих пор я пытался создать реализацию IUserType, чтобы попытаться справиться с этим.Однако я не знаю, что возвращать для SqlType[] SqlTypes.Я рассматривал новый SqlType(DbType.Object), но когда я пытаюсь сгенерировать схему из этого, я получаю System.ArgumentException:Диалект не поддерживает DbType.Object

Если я попробую другой тип данных, то при попытке преобразовать этот тип я получаю различные исключения приведения.Например, если я использую DbType.Binary и устанавливаю someValue в int32, при попытке фиксации я получаю System.InvalidCastException:Не удалось преобразовать объект типа 'System.Int32' в тип 'System.Байт[]'.

Есть ли способ добиться этого?

Прилагаемый ниже код для нерабочей реализации IUserType (основанный на http://intellect.dk/post/Implementing-custom-types-in-nHibernate.aspx )

public class DataElementType : IUserType

    {
        SqlType baseType = new SqlType(DbType.Binary);
        public SqlType[] SqlTypes
        {
            get
            {
                return new[] { baseType };
            }
        }

        public System.Type ReturnedType
        {
            get { return typeof(object); }
        }

        public new bool Equals(object x, object y)
        {
            if (x == null)
                return false;
            else
                return x.Equals(y);
        }

        public int GetHashCode(object x)
        {
            return x.GetHashCode();
        }

        public object NullSafeGet(IDataReader rs, string[] names, object owner)
        {
            return rs[names[0]];
        }

        public void NullSafeSet(IDbCommand cmd, object value, int index)
        {
            var param = new SQLiteParameter(baseType.DbType, value);
            cmd.Parameters.Insert(index, param);
        }

        public object DeepCopy(object value)
        {
            if (value == null) return null;
            return value;
        }

        public bool IsMutable
        {
            get { return false; }
        }

        public object Replace(object original, object target, object owner)
        {
            return original;
        }

        public object Assemble(object cached, object owner)
        {
            return cached;
        }

        public object Disassemble(object value)
        {
            return value;
        }
    }
Это было полезно?

Решение

Оказывается, чтобы обойти проблему с тем, что SqlType(DbType.Object) не поддерживается диалектом, мы делаем его поддерживаемым путем создания подкласса SQLiteDialect с явной поддержкой:

public class SQLiteDialectWithManifestTyping : SQLiteDialect
{
    public SQLiteDialectWithManifestTyping() : base()
    {
        base.RegisterColumnType(DbType.Object, "NONE");
    }
}

Чтобы использовать этот диалект во Fluent, вызовите Dialect() в вашем объекте SQLiteConfiguration.В NHibernate соответствующим образом задайте диалект свойства конфигурации (см. Раздел 3.5.1 руководства по ссылке).

Затем мы можем применить приведенную выше реализацию DataElementType для наших сопоставлений (необходимо изменить определение SqlTypes на это:

    public SqlType[] SqlTypes
    {
        get
        {
            return new[] { new SqlType(DbType.Object) };
        }
    }

Примечания:

  1. Это не идеально.Существует тенденция переводить все дискретные числа в Int64, а значения с плавающей точкой - в double.

  2. Не существует неявного способа хранения больших значений без знака (например,значения ulong >= long.MaxValue) но это общая проблема sqlite (и, возможно, общая проблема ado.net?).

  3. Из-за потери проверки во время компиляции, вероятно, желательно поместить некоторые проверки во время выполнения в метод NullSafeSet, чтобы убедиться, что значение является примитивным типом.Попытка сохранить общие объекты, по-видимому, просто приводит к вызову метода objects toString().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top