Entity framework core EF核心中的EF.Property能否与相关对象属性一起工作

Entity framework core EF核心中的EF.Property能否与相关对象属性一起工作,entity-framework-core,Entity Framework Core,我正在使用内置的Ef Core Ef.Property函数构建一个动态过滤器函数 private static IQueryable<T> Filter<T>(this IQueryable<T> source, string propertyName, string filterValue) { return source.Where(c => EF.Functions.Like(EF.Property<st

我正在使用内置的Ef Core Ef.Property函数构建一个动态过滤器函数

 private static IQueryable<T> Filter<T>(this IQueryable<T> source, string propertyName, string filterValue)
 {
     return source.Where(c =>
            EF.Functions.Like(EF.Property<string>(c, propertyName).ToLower(), $"{filterValue}%".ToLower()));
 }

有解决办法吗?

那么,
EF.Property
不是一个好的选择。 下面的代码包含一些表达式树“魔力”,但我希望它对创建其他扩展有帮助

公共静态IQueryable筛选器(此IQueryable源、string propertyName、string filterValue)
{
var param=表达式参数(类型(T),“e”);
var body=(表达式)param;
foreach(propertyName.Split('.')中的变量propName)
{
body=Expression.PropertyOrField(body,propName);
}
body=Expression.Call(body,“ToLower”,Type.EmptyTypes);
body=Expression.Call(typeof(DbFunctionsExtensions),“Like”,Type.EmptyTypes,
Expression.Constant(EF.Functions),body,Expression.Constant($“{filterValue}%”.ToLower());
var lambda=表达式.lambda(body,param);
var queryExpr=Expression.Call(typeof(Queryable),“Where”,new[]{typeof(T)},source.Expression,lambda);
返回source.Provider.CreateQuery(queryExpr);
}

所以,那么
EF.Property
不是一个好的选择。 下面的代码包含一些表达式树“魔力”,但我希望它对创建其他扩展有帮助

公共静态IQueryable筛选器(此IQueryable源、string propertyName、string filterValue)
{
var param=表达式参数(类型(T),“e”);
var body=(表达式)param;
foreach(propertyName.Split('.')中的变量propName)
{
body=Expression.PropertyOrField(body,propName);
}
body=Expression.Call(body,“ToLower”,Type.EmptyTypes);
body=Expression.Call(typeof(DbFunctionsExtensions),“Like”,Type.EmptyTypes,
Expression.Constant(EF.Functions),body,Expression.Constant($“{filterValue}%”.ToLower());
var lambda=表达式.lambda(body,param);
var queryExpr=Expression.Call(typeof(Queryable),“Where”,new[]{typeof(T)},source.Expression,lambda);
返回source.Provider.CreateQuery(queryExpr);
}

另一种解决方案,更复杂但功能强大。这个想法是让C#编译器能够创建表达式树,并在最后纠正它们

使用简单,但可重复使用:

string filterValue=“A”;
query=query.FilterByPattern(“Customer.CompanyName”,
(字符串v)=>EF.Functions.Like(v.ToLower(),$“{filterValue}%”);
使用此扩展编写的过滤器函数与问题中描述的相同

公共静态IQueryable筛选器(此IQueryable查询、字符串propPath、字符串filterValue)
{
返回query.FilterByPattern(propPath,
(字符串v)=>EF.Functions.Like(v.ToLower(),$“{filterValue}%”);
}
和执行:

公共静态类查询扩展
{
公共静态IQueryable FilterByPattern(此IQueryable查询,字符串路径,
表达式谓词模式(predicatePattern)
{
返回query.Where(MakePredicate(propPath,predicatePattern));
}
公共静态表达式GetPath(表达式obj,字符串propPath)
{
如果(!string.IsNullOrEmpty(propPath))
{
foreach(propPath.Split('.')中的变量propName)
{
obj=Expression.PropertyOrField(obj,propName);
}
}
返回obj;
}
公共静态表达式MakePredicate(字符串propPath,
表达式谓词模式(predicatePattern)
{
var param=表达式参数(类型(T),“e”);
var body=GetPath(param,propPath);
body=ExpressionReplacer.GetBody(谓词模式,body);
返回表达式.Lambda(body,param);
}
类ExpressionReplacer:ExpressionVisitor
{
只读IDictionary _replaceMap;
public ExpressionReplacer(IDictionary replaceMap)
{
_replaceMap=replaceMap??抛出新的ArgumentNullException(nameof(replaceMap));
}
公共重写表达式访问(表达式扩展)
{
if(exp!=null&&u replaceMap.TryGetValue(exp,out var replacement))
退换货;
返回基地访问(exp);
}
公共静态表达式替换(表达式expr、表达式toReplace、表达式toExpr)
{
返回新的ExpressionReplacer(新字典{{toReplace,toExpr}});
}
公共静态表达式替换(表达式表达式表达式、IDictionary替换映射)
{
返回新的ExpressionReplacer(replaceMap)。访问(expr);
}
公共静态表达式GetBody(LambdaExpression lambda,params Expression[]toReplace)
{
if(lambda.Parameters.Count!=toReplace.Length)
抛出新的InvalidOperationException();
返回新的ExpressionReplacer(lambda.Parameters.Zip(toReplace)
.ToDictionary(e=>(表达式)e.First,e=>e.Second)).Visit(lambda.Body);
}
}

另一种解决方案,更加复杂但功能强大。其思想是使C#编译器能够创建表达式树,并在最后更正它们

使用简单,但可重复使用:

string filterValue=“A”;
query=query.FilterByPattern(“Customer.CompanyName”,
(字符串v)=>EF.Functions.Like(v.ToLower(),$“{filterValue}%”);
使用此扩展编写的过滤器函数与问题中描述的相同

公共静态IQueryable筛选器(此IQueryable查询、字符串propPath、字符串filterValue)
{
返回query.FilterByPattern(propPath,
(字符串v)=>EF.Functions.Like(v.ToLower(),$“{filterValue}%”);
}
和执行:

公共静态类查询扩展
{
公共静态IQueryable FilterByPattern(此IQueryable查询,字符串路径,
表达式谓词模式(predicatePattern)
{
返回query.Where(MakePredicate(propPath,predicatePattern));
}
公共静态表达式GetPat
query = query.Where(x => EF.Functions.Like(x.Customer.CompanyName.ToLower(), ""));