.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 ...
随机推荐
- 动态创建 Lambda 表达式
首先我们看一个简单 Lambda 表达式的构成. i => i > 5 在这个表达式中,"i" 被称为 Parameter,"i > 5" 是 ...
- Java基础学习(三)
/* java中的八种基本数据类型: 整数: byte . short . int . long 小数: float double 字符: char 布尔: boolean 字符串的类型: Strin ...
- flume使用示例
flume的特点: flume是一个分布式.可靠.和高可用的海量日志采集.聚合和传输的系统.支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受 ...
- 安装HBase
安装HBase 1.默认已经安装好java+hadoop+zookeeper 2.下载对应版本的HBase 3.解压安装包 tar zxvf hbase-1.0.2-bin.tar.gz 4.配置环境 ...
- 详细讲述MySQL中的子查询操作 (来自脚本之家)
继续做以下的前期准备工作: 新建一个测试数据库TestDB: ? 1 create database TestDB; 创建测试表table1和table2: ? 1 2 3 4 5 6 7 8 9 1 ...
- Vue - 自定义指令
1.Vue.directive(id,definition)注册一个全局自定义指令,接收两个参数,指令ID以及定义对象 2.钩子函数:将作用域与DOM进行链接,链接函数用来创建可以操作DOM的指令 b ...
- 丢手帕问题即约瑟夫问题的PHP解法
问题描述:n个人排成一圈.从某个人开始,依次报数,数到m的人被杀死.下一个人重新从1开始报数,数到m的人被杀死.直到剩下最后一个人. 解决思路:从数学角度去看,每一次报数决定谁去死是一个n.m的求余数 ...
- iOS 面试题搜集
1.#import和#include的区别,@class代表什么? 2.浅拷贝和深拷贝区别是什么? 3.Objective-C中类别和类扩展的区别? 4.Objective-C堆和栈的区别? 5.内存 ...
- three.js全景
<!DOCTYPE html> <html lang="en"> <head> <title>three.js webgl - eq ...
- linux kernel elv_queue_empty野指针访问内核故障定位与解决
1. 故障描述 故障操作步骤: 单板上插了一个U盘,出问题前正在通过FTP往单板上拷贝文件,拷贝的过程中单板自动重启. 故障现象: Entering kdb (current=0xc000000594 ...