Lambda 表达式编译(== 和等于 char)
Lambda expression compilation (== and equal with char)
在表达式中使用 ==
和 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='А'
谓词的相同查询,它不会'不关心过滤器表达式中使用的真实字符值!
这看起来像 NHibernate 缓存或类似的东西?
这是一个known bug。您可以在 char
属性 上调用 .ToString()
并将字面值作为字符串提供以避开错误,但我不确定。
其根源在于某些.Net编译规则导致char
在lambda表达式中被转换为int
。
目前在 master 分支中修复(即将发布的 v5),我不知道它是否可以移植到 v4。
在表达式中使用 ==
和 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='А'
谓词的相同查询,它不会'不关心过滤器表达式中使用的真实字符值!
这看起来像 NHibernate 缓存或类似的东西?
这是一个known bug。您可以在 char
属性 上调用 .ToString()
并将字面值作为字符串提供以避开错误,但我不确定。
其根源在于某些.Net编译规则导致char
在lambda表达式中被转换为int
。
目前在 master 分支中修复(即将发布的 v5),我不知道它是否可以移植到 v4。