需求来源:界面上要筛选一个列表数据,比如爱好这个字段,数据库存储是多个爱好,逗号隔开,比如:篮球,羽毛球,乒乓球;我现在界面上是一个多选搜索框,可以同时包含多个爱好项目
如下数据:
姓名 | 爱好(hobby)字段 |
张三 | 篮球,足球 |
李四 | 篮球,羽毛球 |
王二 | 羽毛球,棒球 |
当我界面勾选了棒球和足球的时候,入参如下
{"hobby":["棒球","足球"]}
我应该把张三和王二筛选出来
于是乎,我后台用List<string> model接收到参数
db.table.Where(x=> model.Any(y => x.hobby.Contains(y)) )
EFCore直接告诉我,这个写法无法解释
所以开始自己的封装
/// <summary> ///扩展 ContainsAny /// 字段包含数组中的任意一个 /// .ContainsAny(model.JobKeyWrods.Count>0, x =>x.KeyWords,model.JobKeyWrods) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="q">The q.</param> /// <param name="condition">if set to <c>true</c> [condition].</param> /// <param name="text">The text.</param> /// <param name="items">The items.</param> /// <returns></returns> public static IQueryable<T> ContainsAny<T>(this IQueryable<T> q, bool condition, Expression<Func<T, string>> text, List<string> items) { if (!condition) { return q; } Expression<Func<T, bool>> predicate = c => false; // var contains = typeof(string).GetMethod("Contains"); var contains = typeof(string).GetMethod("Contains", new[] { typeof(string) }); foreach (var item in items) { var containsExpression = Expression.Call(text.Body, contains, Expression.Constant(item, typeof(string))); var lambda = Expression.Lambda<Func<T, bool>>(containsExpression, text.Parameters); predicate = predicate.Or(lambda); } return q.Where(predicate); } // <summary> /// Or连接 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="expr1">The expr1.</param> /// <param name="expr2">The expr2.</param> /// <returns></returns> public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters); }
这时,改下我们的调用
db.table.ContainsAny(model.Count>0,x.hobby,model)
此时发现,我们的EFCore生成的Sql已经满足我们的要求
select * from table where hobby like '%棒球%' or hobby like '%足球%'
留下您的脚步
最近评论