NHibernate linq запрос с IUserType - PullRequest
       27

NHibernate linq запрос с IUserType

11 голосов
/ 15 августа 2011

В моем проекте я использую IUserType (BooleanM1), который обрабатывает логические значения и записывает -1 для true и 0 для false в базу данных.Пока все работает хорошо.Отображение выглядит следующим образом:

<property name="Active" column="ACTIVE" type="Core.Persistence.NH.Types.BooleanM1,Core.Test"/>

Поэтому, если я выполняю запрос, подобный следующему

var pList = Session.Query<Test>().Where( c => c.Active ).ToList();

, генерируется исключение:

NHibernate.QueryException: Unable to render boolean literal value [.Where[Core.Test.Domain.Test]
(NHibernate.Linq.NhQueryable`1[Core.Test.Domain.Test], Quote((c, ) => (c.Active)), )] 
---> System.InvalidCastException: Das Objekt des Typs "NHibernate.Type.CustomType" kann nicht 
in Typ "NHibernate.Type.BooleanType" umgewandelt werden.

Реализация BooleanM1выглядит так:

{
  public class BooleanM1 :  IUserType
  {
     public bool IsMutable
     {
       get { return false; }
     }

     public Type ReturnedType
     {
        get { return typeof(bool); }
     }

     public SqlType[] SqlTypes
     {
        get { return new[]{NHibernateUtil.Int16.SqlType}; }
     }

     public object NullSafeGet(IDataReader rs, string[] names, object owner)
     {
        var obj = NHibernateUtil.String.NullSafeGet(rs, names[0]);

        if(obj == null ) return false;

        return ((string)obj == "-1" || (string)obj == "1") ? true : false;
     }

     public void NullSafeSet(IDbCommand cmd, object value, int index)
     {
        if(value == null)
        {
          ((IDataParameter) cmd.Parameters[index]).Value = DBNull.Value;
        }
        else
        {
          ((IDataParameter) cmd.Parameters[index]).Value = (bool)value ? -1 : 0;
        }
     }

     public object DeepCopy(object value)
     {
        return value;
     }

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

     public new bool Equals(object x, object y)
     {
       if( ReferenceEquals(x,y) ) return true;

       if( x == null || y == null ) return false;

       return x.Equals(y);
     }

     public int GetHashCode(object x)
     {
        return x == null ? typeof(bool).GetHashCode() + 473 : x.GetHashCode();
     }
}

Это известная ошибка в поставщике linq или что-то не так с моим UserType?Любая помощь приветствуется.

Ответы [ 3 ]

9 голосов
/ 11 апреля 2012

У меня была похожая проблема с UserType, который делает почти то же самое.Я обнаружил, что точное указание равенства в моих запросах решило проблему.

Попробуйте перейти от:

var pList = Session.Query<Test>().Where( c => c.Active ).ToList();

к:

var pList = Session.Query<Test>().Where( c => c.Active == true ).ToList();

По какой-то причине поставщик Linq от NHibernateзатем может понять это.

2 голосов
/ 01 сентября 2011

Вы уже решили это?

Не уверен, что это та же проблема, но у меня было нечто похожее, когда поле базы данных было обнуляемым, а пользовательский тип указывает, что вы возвращаете "bool" -> Возможно, для возврата его нужно изменить на "bool" типа "

 public Type ReturnedType
 {
    get { return typeof(bool?); }
 }
1 голос
/ 28 декабря 2016

Исправлено в версии 4.1.0. Тип пользователя должен реализовывать IEnhancedUserType для корректной работы с исправлением. https://nhibernate.jira.com/browse/NH-2839

...