Можно ли использовать функции печати sqlite манифеста в nhibernate? - PullRequest
1 голос
/ 31 июля 2009

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

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

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

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

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

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

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

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

Прикрепленный код ниже для нерабочей реализации 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;
        }
    }

1 Ответ

1 голос
/ 28 ноября 2009

Оказывается, чтобы обойти проблему с SqlType (DbType.Object), который не поддерживается Dialect, мы делаем его поддерживаемым, создав подкласс 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 и всплывать в два раза.

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

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

...