.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 ...
随机推荐
- Ubuntu(Linux系统)虚拟机工具vmtools详细说明
安装虚拟机工具vmtools大概步骤如下: 个人总结步骤: 第一步:点击虚拟机软件的vm工具栏选项,选择install vmware tools(安装VMware Tools) 第二步:桌面会出现一个 ...
- postgresql数据库备份和恢复
PostgreSQL自带一个客户端pgAdmin,里面有个备份,恢复选项,也能对数据库进行备份 恢复(还原),但最近发现数据库慢慢庞大的时候,经常出错,备份的文件过程中出错的几率那是相当大,手动调节灰 ...
- Python-函数的返回值
特点: - 函数被调用后会返回一个指定的值 - 函数调用后默认返回none - return用于函数内部返回值 - 返回值可以是任意类型 - return执行后,函数终止 注意: 所有函数默认都有 ...
- Nginx - Windows下作为服务启动
Nginx官方没有提供作为服务启动nginx的方案.以服务启动nginx依赖于winsw,当前最新版是1.19. 参考:https://segmentfault.com/a/1190000006807 ...
- LOL(英雄联盟)提示不支持虚拟机登录,解决方法
搜索虚拟系统下的存放文件索 .VMX 会出现带有.VMX 的文件(比如Windows 7.vmx)用记事本打开在最后面回车再加入一行:monitor_control.restrict_backdoor ...
- Linux学习笔记(16)-多线程
什么是多线程?或者说,什么是线程? 按照书本上的描述,所谓线程,便是包含在进程内部的顺序执行流,是进程中实际运作的单位,也是操作系统能够进行调度的最小单位. 一个进程中可以并发多条线程,每条线程并行执 ...
- 数组中pop()和reverse()方法调用
数组的倒序排列,可以采用reverse()和pop()方法进行排列.
- 丢掉慢吞吞的AVD吧,android模拟神器:Genymotion
安装图文介绍: http://padhz.com/how-to-run-android-simulator-on-pc.html; 刚好手头上有visual box,亲自试用了一下.新建了一个Gala ...
- LNMP虚拟机开发环境配置--vagrant+virtualbox+ubuntu14.04
工作一直用的是别人打包好的虚拟机开发环境,感觉确实很酷.所以准备自己配个开发环境,为之后自己开发一些有趣的东西做准备. ok,开始~~~ 一.安装软件 vagrant和virtualbox 此处需注意 ...
- solr update接口常用方法
solr索引数据更新接口:http://localhost:8080/solr/update 有以下一些操作可以通过update接口完成,只能使用post的形式提交数据. 1.添加索引 确保field ...