如何在 C# 中使用表达式创建动态 lambda 连接查询?

How to create dynamic lambda join query using expression in C#?

我是动态表达式查询的新手...

我想动态创建连接查询。在它下面是我想要等效动态查询的查询:

var lstNums = new List<int> { 100, 101 }; 
var getAll = new StudenRepository().GetAll(); //Returns IQuerable<Student>

var query = getAll.Join(lstNums, a => a.StudentId, b => b, (a, b) => a).ToList(); 
  1. lstNums可以是任何原始数据类型的列表
  2. getAll包含IQuerable,这个可以是任意实体的IQuerable
  3. querygetAll 和整数列表进行连接后,将包含 List<Student> 条记录。但结果可以是任何实体列表。列表即 lstNum 可以是原始数据类型的任何列表。

下面是我试过的:

public static IQueryable JoinQuery(this IQueryable outer, IEnumerable innerEntities, string firstEntityPropName, 
    Type typeSecondEntity, Type typeResultEntity, params object[] values)
{
    LambdaExpression outerSelectorLambda = DynamicLinq.DynamicExpression.ParseLambda(outer.ElementType, null, firstEntityPropName, values);

    ParameterExpression expnInput = Expression.Parameter(typeSecondEntity, "inner");
    ParameterExpression expnResult = Expression.Parameter(typeResultEntity, "outer");               

    return outer.Provider.CreateQuery(
       Expression.Call(
           typeof(Queryable), "Join",
           new Type[] { outer.ElementType, innerEntities.AsQueryable().ElementType, outerSelectorLambda.Body.Type, expnResult.Type },
           outer.Expression, innerEntities.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), expnInput,
           expnResult));
}

扩展方法:

public static IQueryable<T> JoinQuery<T>(this IQueryable outer, IEnumerable innerEntities, string firstEntityPropName, Type typeSecondEntity, Type typeResultEntity, params object[] values)
{
    return (IQueryable<T>)Extensions.JoinQuery((IQueryable)outer, (IEnumerable)innerEntities, firstEntityPropName, typeSecondEntity, typeResultEntity, values);
}

注意:我已经为动态 linq 表达式安装了 System.Linq.Dynamic nuget 包版本 1.0.7

下面的代码对我有用:

using DynamicLinq = System.Linq.Dynamic;
using LinqExpression = System.Linq.Expressions;

public static IQueryable JoinQuery(this IQueryable outer, IEnumerable innerEntities, string firstEntityPropName, 
    Type typeSecondEntity, Type typeResultEntity, params object[] values)
{
    if (innerEntities == null) throw new ArgumentNullException(nameof(innerEntities));
    if (firstEntityPropName == null) throw new ArgumentNullException(nameof(firstEntityPropName));
    if (typeSecondEntity == null) throw new ArgumentNullException(nameof(typeSecondEntity));
    if (typeResultEntity == null) throw new ArgumentNullException(nameof(typeResultEntity));

    LambdaExpression outerSelectorLambda = DynamicLinq.DynamicExpression.ParseLambda(outer.ElementType, null, firstEntityPropName, values);

    ParameterExpression expnInput = Expression.Parameter(typeSecondEntity, "inner");

    ParameterExpression[] parameters = new ParameterExpression[] {
    Expression.Parameter(outer.ElementType, "outer"), Expression.Parameter(innerEntities.AsQueryable().ElementType, "inner")
    };

    LambdaExpression selectorSecondEntity = DynamicLinq.DynamicExpression.ParseLambda(new ParameterExpression[] { expnInput }, typeSecondEntity, "inner");
    LambdaExpression selectorResult = DynamicLinq.DynamicExpression.ParseLambda(parameters, typeResultEntity, "outer");

    return outer.Provider.CreateQuery(
       Expression.Call(
           typeof(Queryable), "Join",
           new Type[] { outer.ElementType, innerEntities.AsQueryable().ElementType, outerSelectorLambda.Body.Type, selectorResult.Body.Type },
           outer.Expression, innerEntities.AsQueryable().Expression, Expression.Quote(outerSelectorLambda), Expression.Quote(selectorSecondEntity),
          Expression.Quote(selectorResult)));
}

扩展方法如下:

public static IQueryable<T> JoinQuery<T>(this IQueryable outer, IEnumerable innerEntities, string firstEntityPropName, Type typeSecondEntity, Type typeResultEntity, params object[] values)
{
    return (IQueryable<T>)Extensions.JoinQuery((IQueryable)outer, (IEnumerable)innerEntities, firstEntityPropName, typeSecondEntity, typeResultEntity, values);
}