我正在使用 VS2022 并使用 EF Core。我的数据上下文是 _myLab05Context,我有一个实体“解决方案”,它有一个导航属性“SolutionUsages”。 SolutionUsages 有一个属性“StudyId”。例如,我想检索 SolutionUsages.StudyId == 5 的所有解决方案。我可以使用以下代码执行此操作:
var query = await _myLab05Context.Solutions
.Select(s => new
{
Solutions = s,
SolutionUsages = s.SolutionUsages.Where(su => su.StudyId == 5)
})
.Where(s => s.SolutionUsages.Any(su => su.StudyId == 5))
.ToListAsync();
效果很好。作为动态方法的第一步,我生成了两个表达式:
var anyQuery =
_buildWhereExpression.GenericAny<Entities.Solution, Entities.SolutionUsage>("SolutionUsages",
"StudyId", 5L);
var whereQuery =
_buildWhereExpression.GenericWhere<Entities.Solution, Entities.SolutionUsage>("SolutionUsages",
"StudyId", 5L);
anyQuery 是 Expression
public Expression<Func<TSource, bool>> GenericAny<TSource, T2ndSource>(string navPropName, string propName, long propValue)
{
ParameterExpression pe02 = Expression.Parameter(typeof(T2ndSource), "x");
MemberExpression me02 = Expression.Property(pe02, propName);
ConstantExpression constant = Expression.Constant(propValue);
BinaryExpression body = Expression.Equal(me02, constant);
var funcExpression = Expression.Lambda<Func<T2ndSource, bool>>(body, pe02);
ParameterExpression pe = Expression.Parameter(typeof(TSource), "s");
MemberExpression me = Expression.Property(pe, navPropName);
var navPropType = typeof(T2ndSource);
var anyCall = Expression.Call(typeof(Enumerable), nameof(Enumerable.Any), new[] { navPropType }, me, funcExpression);
var predicate = Expression.Lambda<Func<TSource, bool>>(anyCall, pe);
return predicate;
}
public Expression<Func<T2ndSource, bool>> GenericWhere<TSource, T2ndSource>(string navPropName, string propName, long propValue)
{
ParameterExpression pe02 = Expression.Parameter(typeof(T2ndSource), "x");
MemberExpression me02 = Expression.Property(pe02, propName);
ConstantExpression constant = Expression.Constant(propValue);
BinaryExpression body = Expression.Equal(me02, constant);
var funcExpression = Expression.Lambda<Func<T2ndSource, bool>>(body, pe02);
return funcExpression;
}
(我知道 whereQuery 已经是 anyQuery 的一部分,但我将它们分开保存以分离错误。)
当我用“whereQuery”替换第一个 where-clause 时,我在“where”行中得到一个错误:
错误 CS1929“ICollection”不包含“Where”的定义,最佳扩展方法“Queryable.Where(IQueryable, Expression
当我用“anyQuery”替换第二个 where 子句时,出现错误
错误 CS1503 参数“2”:从“System.Linq.Expressions.Expression
如何修改表达式以便它们在查询中起作用?
我不完全确定我是否理解你正在尝试做的事情。以动态方式执行此操作可能会有点混乱。
我不确定我是否理解您的用例。但是,如果您的问题是应用表达式,那么最后一部分应该可以正常工作。
知道导航属性的类型时执行此操作的简单方法如下:
public static Expression<Func<TSource, TResult>> Combine<TSource, TProp, TResult>(
Expression<Func<TSource, TProp>> selectExpression,
Expression<Func<TProp, TResult>> transformExpression)
{
var sourceParameter = propertyExpression.Parameters[0];
var propertyAccess = propertyExpression.Body;
var transformedAccess = Expression.Invoke(transformExpression, propertyAccess);
return Expression.Lambda<Func<TSource, TResult>>(transformedAccess, sourceParameter);
}
public class Solution { public List<Study> SolutionUsages { get; set; } }
public class Study { public int StudyId { get; set; } }
public static void Example()
{
IQueryable<Solution> solutions = new List<Solution>().AsQueryable();
var exprWhereAny = ExprHelp.Combine<Solution, List<Study>, bool>(
container => container.SolutionUsages,
list => list.Any(s => s.StudyId == 5));
var exprWhere = ExprHelp.Combine<Solution, List<Study>, IEnumerable<Study>>(
container => container.SolutionUsages,
list => list.Where(s => s.StudyId == 5))
.Compile();
var query = solutions
.Where(exprWhereAny)
.Select(s => new
{
Solutions = s,
SolutionUsages = exprWhere.Invoke(s)
})
.ToList();
...
}
希望这至少能帮到你。