.NET Core中合并Expression<Func<T,bool>>的正确姿势
这是在昨天的 .NET Core 迁移中遇到的问题,之前在 .NET Framework 中是这样合并 Expression<Func<T,bool>> 的:
public static class ExpressionBuilder
{
public static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
{
var map = first.Parameters.Select((f, i) => new { f, s = second.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
} public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.And);
} public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
{
return first.Compose(second, Expression.Or);
}
}
迁移至 .NET Core 之后,Entity Framework Core 生成了不正确的 SQL 语句:
WHERE (CASE
WHEN ([q0].[IsActive] = 1) AND ([q.questionUser0].[IsActive] = 1)
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END & CASE
WHEN [q0].[DealFlag] = 0
THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
END) AND (([q0].[Flags] & @__flags_0) = @__flags_1)
在 Server Server 中执行时会出现如下的错误:
在应使用条件的上下文(在 'AND' 附近)中指定了非布尔类型的表达式
后来参考 Combining two expressions (Expression<Func<T, bool>>),通过下面的代码解决了问题:
public static class ExpressionBuilder
{
public static Expression<Func<T, bool>> And<T>(
this Expression<Func<T, bool>> first,
Expression<Func<T, bool>> second)
{
return first.AndAlso<T>(second, Expression.AndAlso);
} public static Expression<Func<T, bool>> Or<T>(
this Expression<Func<T, bool>> first,
Expression<Func<T, bool>> second)
{
return first.AndAlso<T>(second, Expression.OrElse);
} private static Expression<Func<T, bool>> AndAlso<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2,
Func<Expression, Expression, BinaryExpression> func)
{
var parameter = Expression.Parameter(typeof(T)); var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[], parameter);
var left = leftVisitor.Visit(expr1.Body); var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[], parameter);
var right = rightVisitor.Visit(expr2.Body); return Expression.Lambda<Func<T, bool>>(
func(left, right), parameter);
} private class ReplaceExpressionVisitor
: ExpressionVisitor
{
private readonly Expression _oldValue;
private readonly Expression _newValue; public ReplaceExpressionVisitor(Expression oldValue, Expression newValue)
{
_oldValue = oldValue;
_newValue = newValue;
} public override Expression Visit(Expression node)
{
if (node == _oldValue)
return _newValue;
return base.Visit(node);
}
} }
.NET Core中合并Expression<Func<T,bool>>的正确姿势的更多相关文章
- EF Core 封装方法Expression<Func<TObject, bool>>与Func<TObject, bool>区别
unc<TObject, bool>是委托(delegate) Expression<Func<TObject, bool>>是表达式 Expression编译后就 ...
- lambda表达式Expression<Func<Person, bool>> 、Func<Person, bool>区别
前言: 自己通过lambda表达式的封装,将对应的表达式转成字符串的过程中,对lambda表达式有了新的认识 原因: 很多开发者对lambda表达式Expression<Func<Pers ...
- .NetCore 扩展封装 Expression<Func<T, bool>> 查询条件遇到的问题
前面的文章封装了查询条件 自己去组装条件,但是对 And Or 这种组合支持很差,但是也不是不能支持,只是要写更多的代码看起来很臃肿 根据 Where(Expression<Func< ...
- Entity Framework 动态构造Lambda表达式Expression<Func<T, bool>>
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; us ...
- Expression<Func<TObject, bool>>与Func<TObject, bool>的区别
Func<TObject, bool>是委托(delegate) Expression<Func<TObject, bool>>是表达式 Expression编译后 ...
- 表达式拼接Expression<Func<IEntityMapper, bool>> predicate
/// <summary> /// 重写以筛选出当前上下文的实体映射信息 /// </summary> protected override IEnumerable<IE ...
- Expression<Func<T, bool>>
public static Expression<Func<T, bool>> True<T>() { return f => true; } public ...
- 拉姆达表达式 追加 条件判断 Expression<Func<T, bool>>
public static class PredicateBuilder { /// <summary> /// 机关函数应用True时:单个AND有效,多个AND有效:单个OR无效,多个 ...
- Expression<Func<T, bool>>与Func<T, bool>的区别
转自:http://www.cnblogs.com/wow-xc/articles/4952233.html Func<TObject, bool>是委托(delegate) Expres ...
随机推荐
- 2017年第1贴:EXT.JS使用MVC模式时,注意如何协调MODEL, STORE,VIEW,CONTROLLER的关系
也调了快一天,死活找不到窍门. MODEL, STORE,VIEW的调置测试了很久,试了N种方法,不得其果. 最后,试着在APPLICATION里加入CONTROLLER, 在CONTROLLER里加 ...
- centos+scala2.11.4+hadoop2.3+spark1.3.1环境搭建
一.Java安装 1.安装包准备: 首先到官网下载jdk,http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads- ...
- 关于Knockout的开始
最近看了汤姆大叔的Knockout,感到MVVM的神奇,也许这就是以后编程的方式,最直观的感觉就是层次更分明了. 绑定,模型转换,监控,在我来说,这算是编程上的一个转变,在以后我做不定期的更新一些MV ...
- VS Code 配置Python
1. 安装VS Code的Python插件,选择安装次数最多的那个 2. 点击用户设置菜单,在settings.json中添加 "python.pythonPath": " ...
- 对Raphael画图标的一个jquery简单封装
公司要做一个项目的demo,要求地图上可以插红旗,所以就用到了Raphael. 因为是个demo,所以地图就用了一张图片,效果如下: 所以为了更好的封装一下这个功能,就写了一个简单的插件:jquery ...
- FZU 2137 奇异字符串 后缀树组+RMQ
题目连接:http://acm.fzu.edu.cn/problem.php?pid=2137 题解: 枚举x位置,向左右延伸计算答案 如何计算答案:对字符串建立SA,那么对于想双延伸的长度L,假如有 ...
- #英文#品读中国城市个性——秦汉雄风&和祖先在一起
妨碍 interfere with 仇恨 hatred 坍塌 collapse 专制君主 autocratic dictator 排除异己 suppress opposition 被逼到绝望边缘 b ...
- echarts中显示效果option中必有的属性
写一个最简单的效果让option中不可缺少的属性. var option = { xAxis:[ //x轴,数组对象,其下至少有一个对象 {.....} ], yAxis:[//y轴,数组对象,其下可 ...
- ViewPager 简单实现左右无限滑动.
只需在在适配器中将getCount 给一个较大的值, 然后将currentItem 设为值的一半 就可以伪实现 无限循环. private static final int PAGE_COUNT = ...
- .NET开发人员必看:提高ASP.NET Web应用性能的24种方法和技巧
那性能问题到底该如何解决?以下是应用系统发布前,作为 .NET 开发人员需要检查的点. 1.debug=「false」 当创建 ASP.NET Web应用程序,默认设置为「true」.开发过程中,设置 ...