问题 使用IUserType的NHibernate linq查询


在我的项目中,我使用一个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有问题?任何帮助表示赞赏。


12813
2017-08-15 10:35


起源



答案:


我有一个类似的问题,UserType做了几乎相同的事情。我发现在我的查询中明确说明相等性解决了这个问题。

试着去:

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

至:

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

出于某种原因,NHibernate的Linq提供商可以解决这个问题。


9
2018-04-11 19:15



谢谢!我试了一下它完美无缺:-) - Belvasis


答案:


我有一个类似的问题,UserType做了几乎相同的事情。我发现在我的查询中明确说明相等性解决了这个问题。

试着去:

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

至:

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

出于某种原因,NHibernate的Linq提供商可以解决这个问题。


9
2018-04-11 19:15



谢谢!我试了一下它完美无缺:-) - Belvasis


你解决了吗?

不确定它是否是同一个问题,但我有类似的东西,数据库字段可以为空,自定义类型指定你返回“bool” - >它可能需要更改为“bool?for return type”

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

2
2017-09-01 07:42



我也在寻找解决方案。我在NullSafeGet()中设置了一个断点,并且代码执行没有到达它,因此Linq where子句不会调用IUserType转换。 - DaBozUK
不,我没有解决这个问题。我尝试了你的建议,但结果是一样的。我认为这是LINQ实现的一个问题。如果我将UserType与QueryOver一起使用,它将按预期工作。 - Belvasis


已在4.1.0版中修复。 用户类型应该实现IEnhancedUserType以正确使用修复程序。 https://nhibernate.jira.com/browse/NH-2839


0
2017-12-28 18:12