简体   繁体   中英

Better way to Sort a Queryable by any property

This case is similar to Better way to Sort a List by any property , but in this case doesn't has list in memory before execute the method '.ToList()'.

I want to sort before the database query be executed. I want to 'write' the SQL Query before his execution.

My code:

public virtual DataTablesData<TViewModel> DataTablesGetData(DataTablesParam model)
{
    var paged = new DataTablesData<TViewModel>();
    IQueryable<TEntity> qr;

    try
    {
        using (var db = new EdmxMSSQLContainer())
        {
            List<TViewModel> list = null;

            qr = db.Set<TEntity>();

            int iColumn = model.Order.FirstOrDefault().Column;
            var property = typeof(TEntity).GetProperty(model.Columns.ToArray()[iColumn].Data);
            var param = Expression.Parameter(typeof(TEntity));
            Expression final = Expression.Property(param, property);

            if (property.PropertyType.IsValueType)
            {
                final = Expression.MakeUnary(ExpressionType.Convert, final, typeof(object));
            }

            var lambda = Expression.Lambda<Func<TEntity, object>>(final, param);

            if (model.Order.FirstOrDefault().Dir.Equals("asc"))
            {
                qr = qr.OrderBy(lambda);
            }
            else
            {
                qr = qr.OrderByDescending(lambda);
            }

            // THIS LINE THROW EXCEPTION
            // qr.ToList() execute SQL Query
            list = Mapper.Map(qr.ToList(), list);

            paged.recordsTotal = this.CountRecords();
            paged.recordsFiltered = list.Count();
            paged.data = list;
        }
    }
    catch (Exception ex)
    {
        OnError(ex);
    }

    return paged;
}

This line throw exception:

list = Mapper.Map(qr.ToList(), list);

Exception:

Unable to cast the type System.Int32 to type System.Object. LINQ to Entities only supports casting EDM primitive or enumeration types

I found a better way to do this. I had to do this steps:

1 - Add the package "Linq Dynamic" in project:

Install-Package System.Linq.Dynamic.Library

2 - Import the package in Class:

using System.Linq.Dynamic;

3 - Order queryable by the string name of property:

qr.OrderBy(stringPropertyName);                 //asc
qr.OrderBy(stringPropertyName + " descending"); //des

It work perfectly for me.

You could try this :

    Func<IQueryable<Entity>, IOrderedQueryable<Entity>> orderBy = query => query.OrderBy(e => e.ID);

                Expression<Func<Entity, bool>> fitler = e => e.Active;  


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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM