0

I have method below FilterQuery which sorts the data based on sortPropertyName property.

 private IQueryable<TEntity> FilterQuery(Expression<Func<TEntity, bool>> predicate, string sortPropertyName, OrderBy orderBy = OrderBy.Ascending)
    {
        IQueryable<TEntity> entities = _dbEntitySet;
        entities = (predicate != null) ? entities.Where(predicate) : entities;
        if (string.IsNullOrEmpty(sortPropertyName))
        {
            sortPropertyName = "Id";
        }
        var keySelector = CreateSelectorExpression<TEntity>(sortPropertyName);
        entities = (orderBy == OrderBy.Ascending) ? entities.OrderBy(keySelector) : entities.OrderByDescending(keySelector);
        return entities;
    }

Aforementioned method in turn calls method CreateSelectorExpression .

 private static Expression<Func<TEntity, string>> CreateSelectorExpression<TEntity>(string propertyName)
    {
        try
        {
            var paramterExpression = Expression.Parameter(typeof(TEntity));
            return (Expression<Func<TEntity, string>>)Expression.Lambda(Expression.PropertyOrField(paramterExpression, propertyName),
                                                                    paramterExpression);
        }
        catch (Exception ex)
        {
            string msg = ex.ToString();
            return null;
        }
    }

The above solution works fine when the property is of type string but throw exception in case if property type is numeric or date time. For the time being as you can see I have hard-coded the Id property to raise the exception. Here is the exception which CreateSelectorExpression throws when returning expression:

Unable to cast object of type 'System.Linq.Expressions.Expression1[System.Func2[MyProject.Business.Domain.MyClass,System.Int32]]' to type 'System.Linq.Expressions.Expression1[System.Func2[MyProject.Business.Domain.MyClass,System.String]]

Can you please help me what is going on wrong in my code or another better soltion? Also please let me know if you required some more information from me.

Jitender Kumar
  • 1,867
  • 2
  • 22
  • 40

1 Answers1

1

Instead of building your and expression from scratch, you can take an expression over TEntity as key selector in place of the sortPropertyName parameter :

private IQueryable<TEntity> FilterQuery<TValue>(Expression<Func<TEntity, bool>> predicate, Expression<Func<TEntity, TValue>> sortExpression, OrderBy orderBy = OrderBy.Ascending)    
{
    IQueryable<TEntity> entities = _dbEntitySet;         
    entities = (predicate != null) ? entities.Where(predicate) : entities;
    entities = (orderBy == OrderBy.Ascending) ? entities.OrderBy(sortExpression) : entities.OrderByDescending(sortExpression);
    return entities;
}

You can remove the CreateSelectorExpression function.

Example of use :

FilterQuery<Test>(p => p.Id > 50, p => p.Id, OrderBy.Ascending)

Will filter the result by item having the Id greater than 50 and sort them by the Id property.

Fabien PERRONNET
  • 4,227
  • 1
  • 15
  • 31