4

I am new to dynamic expression query. I want to create a join query dynamically. Below it the query for which I want the equivalent dynamic query:

var lstNums = new List<int> { 100, 101 }; 
var getAll = new StudentRepository().GetAll();   // returns IQueryable<Student>

var query = getAll.Join(lstNums, a => a.StudentId, b => b, (a, b) => a).ToList(); 
  1. The lstNums can be list of any primitive data types
  2. The getAll contains IQueryable<Student>, this can be IQueryable<T> of any entity
  3. The query will contain the List<Student> records after doing join with the getAll and list of integers. But the result can be any list of entity. The list i.e. lstNum can be any list of primitive data types.

This is what I have tried:

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));
}

The extension method:

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);
}

Note: I have installed System.Linq.Dynamic nuget package version 1.0.7 for dynamic linq expression.

1 Answer 1

3

The below code worked for me:

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)));
}

The extension method is as follows:

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);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.