1

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

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

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

тип SomeValue в основном в наборе типов .NET IConvertible (примитивы как BOOL, BYTE, полукокса, int16, двойной, плавать и т.д.), плюс байт [] и строка.

Я пытаюсь создать отображение 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; 
     } 
    } 
+0

Ооо ... вы пытаетесь сделать что-то сложное. Удачи: Вы впадаете в сложные воды. –

ответ

1

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

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

Чтобы использовать этот диалект в Fluent, вызовите диалект() на вашем объекте 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().