需求来源:界面上要筛选一个列表数据,比如爱好这个字段,数据库存储是多个爱好,逗号隔开,比如:篮球,羽毛球,乒乓球;我现在界面上是一个多选搜索框,可以同时包含多个爱好项目
如下数据:
| 姓名 | 爱好(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 '%足球%'
川公网安备 51010702003150号
留下您的脚步
最近评论