[英]EF Core - search properties by string
我有一个包含几百列的表,并且从我的客户端我将多个“搜索”对象传递给用于查询该表的服务器。 每个搜索对象都包含一个搜索词,以及与之匹配的属性名称。
我不确定如何在此处使用反射来使用 EF Core 查询属性。 我尝试了以下方法,但它不喜欢它。
var prop = <ENTITYTYPE>.GetProperty(search.Property);
query = context.<ENTITY>.Where(x => (string)prop.GetValue(x) == search.SearchTerm);
我在想我可能必须构建一个原始 SQL 查询,但我很想知道是否有一种方法可以让 EF Core 自己创建查询。 当我在上面执行.ToList()
时,它表示无法翻译查询。
任何帮助,将不胜感激!
这是基本的认识,应该会推动你朝着正确的方向前进:
public static IQueryable<T> AddFilter<T>(IQueryable<T> query, string propertyName, string searchTerm)
{
var param = Expression.Parameter(typeof(T), "e");
var propExpression = Expression.Property(param, propertyName);
object value = searchTerm;
if (propExpression.Type != typeof(string))
value = Convert.ChangeType(value, propExpression.Type);
var filterLambda = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
propExpression,
Expression.Constant(value)
),
param
);
return query.Where(filterLambda);
}
此方法应该适用于单实例实体。
public IQueryable<T> GetBySearchTerm(IQueryable<T> queryable, string search)
{
void GenerateLambda<T>(IProperty columnProp, MethodInfo methodInfo, List<Expression<Func<T, bool>>> expressions)
{
if (columnProp.ClrType == typeof(string))
{
// Define the parameter
ParameterExpression xParam = Expression.Parameter(typeof(T), "x");
// Create the expression representing what column to do the search on
MemberExpression colExpr = Expression.Property(xParam, columnProp.Name);
// Create a constant representing the search value
ConstantExpression constExpr = Expression.Constant(search);
// Generate a method body that represents "column contains search"
MethodCallExpression lambdaBody = Expression.Call(colExpr, methodInfo, constExpr);
// Convert the full expression into a useable query predicate
Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(lambdaBody, xParam);
expressions.Add(lambda);
}
}
T thisEntityBaseModel = new T();
IEntityType set = _dbContext.Model.GetEntityTypes().First(x => x.ClrType.Name.ToUpper() == thisEntityBaseModel.ModelName.ToUpper());
List<Expression<Func<T, bool>>> predicateArray = new List<Expression<Func<T, bool>>>();
MethodInfo containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
foreach (IProperty columnProp in set.GetProperties())
{
GenerateLambda(typeof(T), columnProp, containsMethod, predicateArray);
}
// This performs an "OR" method on the predicates, since by default it wants to do "AND"
var predicate = PredicateBuilder.False<T>();
foreach (Expression<Func<T, bool>> expression in predicateArray) {
predicate = predicate.Or(expression);
}
// Process the ors
return (queryable.Where(predicate));
}
不推荐使用,请参阅我在下面尝试过的示例的评论,它对我有用
private void Test()
{
Type myType = typeof(AktivEvents);
PropertyInfo myPropInfo = myType.GetProperty("AutoReplyMessage");
Func<AktivEvents, bool> func = (e) => (string)myPropInfo.GetValue(e) == "asdasd";
var query = _dbService.AktivEvents.GetAll()
.Where(func)
.ToList();
}
它显然很脏,但这个想法很有效,有依赖关系
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" />
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.