Question

I am using patterns mentioned here http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

And i am using method below to query EF

public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
    {
        IQueryable<TEntity> query = dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

Now i want to create dynamic Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> expression to order my data.

I know only field name as string and order type (ascending, descending) as string (asc, desc)

Was it helpful?

Solution

finally i could write the method i want.

 public static Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> GetOrderBy(string orderColumn, string orderType) {
            Type typeQueryable = typeof(IQueryable<TEntity>);
            ParameterExpression argQueryable = Expression.Parameter(typeQueryable, "p");
            var outerExpression = Expression.Lambda(argQueryable, argQueryable);
            string[] props = orderColumn.Split('.');
            IQueryable<TEntity> query = new List<TEntity>().AsQueryable<TEntity>();
            Type type = typeof(TEntity);
            ParameterExpression arg = Expression.Parameter(type, "x");

            Expression expr = arg;
            foreach(string prop in props) {
                PropertyInfo pi = type.GetProperty(prop, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                expr = Expression.Property(expr, pi);
                type = pi.PropertyType;
            }
            LambdaExpression lambda = Expression.Lambda(expr, arg);
            string methodName = orderType == "asc" ? "OrderBy" : "OrderByDescending";

            MethodCallExpression resultExp =
                Expression.Call(typeof(Queryable), methodName, new Type[] { typeof(TEntity), type }, outerExpression.Body, Expression.Quote(lambda));
            var finalLambda = Expression.Lambda(resultExp, argQueryable);
            return (Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>)finalLambda.Compile();
        }

This method takes two parameters, first one field name other one is asc or desc. Result of method can be used directly with IQueryable object.

Thanks for your helps

OTHER TIPS

This is very late to the party but the correct answer is located on another question at https://stackoverflow.com/a/10935223/14275

var students = repository.Get(x => x.FirstName = "Bob",q => q.OrderBy(s => s.LastName));

I am not sure what exactly you want to accomplish, but I had changed your code and add some example to demonstrate how does it work.

This is a simple console app, which has dummyText as list. Queryable method enables to use filter and sort expression as you want. I hope it helps

 class Program
{

    private List<string> _dummyText = new List<string>(){ "Arda",
        "Araba",
        "Antartika",
        "Balon"};

    static void Main(string[] args)
    {
        Program p = new Program();
        List<string> result = p.Get(s => s.StartsWith("A"), orderBy: q => q.OrderBy(d => d.Length)).ToList();

        Console.ReadLine();
    }


    public virtual IEnumerable<string> Get(
    Expression<Func<string, bool>> filter = null,
    Func<IQueryable<string>, IOrderedQueryable<string>> orderBy = null)
    {

        IQueryable<string> query = _dummyText.AsQueryable();

        if (filter != null)
        {
            query = query.Where(filter);
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }



    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top