.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 ...
随机推荐
- GTest Google的一种白盒单元测试框架 开源项目
GTest为google开源的白盒单元测试跨平台测试框架,含丰富的断言.类型参数化测试.死亡测试.以及其他的测试选项设置.文件保存等,以下将对该项目C++的实现进行简要的分析,作为学习记录备份. 基本 ...
- Jquery的$(selector).each()和$.each()原理和区别
我们都用过Jqurey中的each函数,都知道each()有两种方式去调用,一种是通过$.each()调用,另一种是$(selector).each()去调用,那么它们之间有什么区别? 翻看一下Jqu ...
- Android-Gallery[使用C# And Java实现]
运行效果 C#实现 using Android.App; using Android.OS; using Android.Widget; namespace ImageDemo { [Activity ...
- react native 键盘遮挡按钮点击事件
在做项目的时候,我遇到一个很奇怪的问题,我先描述一下问题,在InputText输入内完成以后,点击按钮进行下一步的操作的时候,第一次点击的时候,按钮没有响应,第二次点击的时候才会响应.这样对用户体验有 ...
- Scrapy创建zentao爬虫
1.安装好Scrapy爬虫框架 2.切换到F盘的wooyun目录下执行:scrapy startproject zentao 这个命令会在当前目录下创建一个新目录zentao,它的结构如下:
- 希尔伯特矩阵(Hilbert matrix)
例: [ 1 1/2 1/3 1/2 1/3 1/4 1/3 1/4 1/5 ] 矩阵的一种,其元素A(i,j)=1/(i+j-1),i,j分别为其行标和列标. 即: [1,1/2,1/3,- ...
- 调用0A中断输入字符串数据段的DUP定义
;这是自动生成的代码模板 STACKS SEGMENT STACK ;堆栈段 DW DUP(?) ;注意这里只有128个字节 STACKS ENDS DATAS SEGMENT ;数据段 STRING ...
- LeetCode 1. Two Sum
Problem: Given an array of integers, return indices of the two numbers such that they add up to a sp ...
- [Leetcode] Contains Duplicate III
Given an array of integers, find out whether there are two distinct indices i and j in the array suc ...
- 图论 - 寻找fly真迹
一天fly正坐在课堂上发呆,突然,他注意到了桌面上的一个字符串S1S2S3S4...Sn,这个字符串只由字符"a","b"和"c"构成.刚好 ...