c# - C# AspNet.Core 请求查询 -> EF Core 谓词表达式
问题描述
通过将查询参数转换为 EF Core 谓词表达式,通过 HTTP 请求在 Azure 终结点访问中最大化客户端大小的 UX。
解决方案
using System;
using System.Linq;
using System.Reflection;
using System.ComponentModel;
using System.Linq.Expressions;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
namespace EMWS_Projects.Services
{
public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
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);
}
public static Expression<Func<T, bool>> And<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.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
public static class QueryToExpressionConverter
{
public static Expression<Func<T, bool>> GetExpressionFromIQueryCollection<T>(IQueryCollection queryCollection)
{
Expression<Func<T, bool>> predicate = PredicateBuilder.True<T>();
foreach (KeyValuePair<string, Microsoft.Extensions.Primitives.StringValues> entry in queryCollection)
{
predicate = predicate.And(GetExpressionFromEntry<T>(entry));
}
return predicate;
}
private static Expression<Func<T, bool>> GetExpressionFromEntry<T>(KeyValuePair<string, Microsoft.Extensions.Primitives.StringValues> entry)
{
PropertyInfo property = typeof(T).GetProperty(entry.Key.Trim(), BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
if (property == null) throw new Exception("Could not derive property from query parameter dictionary key.");
TypeConverter converter = TypeDescriptor.GetConverter(property.PropertyType);
List<string> values = entry.Value.ToList();
if (values == null || values.Count == 0) throw new Exception("Could not parse query parameter's value using the given property.");
Expression<Func<T, bool>> predicate = PredicateBuilder.False<T>();
foreach(string value in values)
{
predicate = predicate.Or((T subject) => typeof(T).GetProperty(entry.Key).GetValue(subject).ToString() == value);
}
return predicate;
}
}
}
推荐阅读
- pytorch - 带有pytorch的resnet50中缺少/意外的键
- excel - 检查单元格的百分比格式
- reactjs - React App S3 托管,Url 参数在 S3 上不起作用
- python-3.x - NameError:名称'DatabaseManage'未在python中定义
- php - 在laravel的foreach循环中迭代元素
- latex - tcolorbox 与 tabular、tabularx 兼容吗?
- laravel - 部署中的 Laravel 和 vue js
- linux - 如何使用 awk 从多个文件中搜索字符串?
- python - PYTHON Pandas:在两个数据框中用字符串求和
- sql - 缺少的括号在哪里?