Lambda表达式编译(==并且等于char)

时间:2017-03-23 09:23:08

标签: c# nhibernate lambda

在表达式中使用==Equals比较char类型变量会在NHibernate中产生不同的SQL查询并导致错误的(优化的?)行为。

我构建了这样的过滤器表达式:

private Expression<Func<T, bool>> BuildFilter<T>(char firstLetter) where T : IEntity
{
    return PredicateBuilder
        .True<T>()
        .And(ft => ft.FirstLetter.Equals(firstLetter));
}

并像这样使用它:

Session.Query<T>().Where(filter)

如果我将char与.Equals进行比较,则会生成下一个查询:

2017-03-23 12:02:52,499 [10] DEBUG NHibernate.SQL - 

select tag0_.Id as col_0_0_ 
  from [ft].[Tags] tag0_ 
 where @p0=1 and tag0_.FirstLetter=@p1 
order by tag0_.Title asc;@p0 = True 

[Type: Boolean (0:0:0)], @p1 = 'А' [Type: StringFixedLength (4000:0:0)]

正如您所看到的,NHibernate创建了FirstLetter变量sql参数(@ p1),这是正确的。

问题

以前,我使用==运算符进行比较,如下所示:

private Expression<Func<T, bool>> BuildFilter<T>(char firstLetter) where T : IEntity
{
    return PredicateBuilder
        .True<T>()
        .And(ft => ft.FirstLetter == firstLetter);
}

这会产生下一个查询:

2017-03-23 12:17:22,718 [23] DEBUG NHibernate.SQL - 

select tag0_.Id as col_0_0_ 
  from [ft].[Tags] tag0_ 
 where @p0=1 
   and tag0_.FirstLetter='А' 
order by tag0_.Title asc;@p0 = True 

[Type: Boolean (0:0:0)]

此查询也是正确的。

但是,只有一点......每次调用带有==比较的方法都会产生相同的查询tag0_.FirstLetter='А'谓词,它并不关心过滤器表达式中使用的真实char值!

那看起来像NHibernate缓存还是类似的东西?

1 个答案:

答案 0 :(得分:1)

这是known bug。您可以在.ToString()属性上调用char并提供文字值作为字符串以避开错误,但我不确定。

它的根源在于.Net编译规则导致char在lambda表达式中转换为int

目前已在主分支(即将发布的v5)中修复,我不知道它是否可以反向移植到v4。