Search code examples
c#.netmongodb-.net-driver

MongoDB Expression System.InvalidOperationException: ' is not supported.'


I am trying to combine 2 query filters with the mongodb driver, but the framework returns just "System.InvalidOperationException: 'x.MyBool2 is not supported.'"

All of the following expressions succeed, except the last one, where I am trying to execute the combined query.

What am I doing wrong?

public async Task GetTest()
{
    Expression<Func<PostDto, bool>> filter = x => x.MyBool1 == true;
    Expression<Func<PostDto, bool>> filter1 = x => x.MyBool2 == true;
    Expression<Func<PostDto, bool>> filter2 = x => x.MyBool1 && x.MyBool2;

    var andAlsoExpression = Expression.AndAlso(filter.Body, filter1.Body);
    var combinedFilter = Expression.Lambda<Func<PostDto, bool>>(andAlsoExpression, filter.Parameters);

    var result = await Collection.AsQueryable().Where(filter).ToListAsync();
    var result1 = await Collection.AsQueryable().Where(filter1).ToListAsync();
    var result2 = await Collection.AsQueryable().Where(filter2).ToListAsync();

    var result3 = await Collection.AsQueryable().Where(x => x.MyBool1 && x.MyBool2).ToListAsync();

    var result4 = await Collection.AsQueryable().Where(combinedFilter).ToListAsync();

    Debugger.Break();
}

Solution

  • Marc Gravell's AndAlso extension helped me:

    static Expression<Func<T, bool>> AndAlso<T>(
        this Expression<Func<T, bool>> expr1,
        Expression<Func<T, bool>> expr2)
    {
        // need to detect whether they use the same
        // parameter instance; if not, they need fixing
        ParameterExpression param = expr1.Parameters[0];
        if (ReferenceEquals(param, expr2.Parameters[0]))
        {
            // simple version
            return Expression.Lambda<Func<T, bool>>(
                Expression.AndAlso(expr1.Body, expr2.Body), param);
        }
        // otherwise, keep expr1 "as is" and invoke expr2
        return Expression.Lambda<Func<T, bool>>(
            Expression.AndAlso(
                expr1.Body,
                Expression.Invoke(expr2, param)), param);
    }
    

    Source: Combining two expressions (Expression<Func<T, bool>>)

    Using this extension, instead of my AndAlso&Expression.Lambda part solved the problem.