I have a repository class as follows. Here my problem is in the GetSelected Method
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected readonly DbContext Db;
protected readonly DbSet<TEntity> DbSet;
public Repository(DbContext context)
{
Db = context;
DbSet = Db.Set<TEntity>();
}
//CRUD Operations
public IEnumerable<TEntity> GetSelected(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, params Expression<Func<TEntity, object>>[] includeProperties)
{
IQueryable<TEntity> query = DbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties)
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
}
I am trying to sort the Department by providing parameters on the fly as follows.
[Route("api/[controller]")]
[ApiController]
public class DepartmentsController : LookupBaseController<Department>
{
private readonly IUowLookups UowLookups;
public DepartmentsController(IUowLookups uowLookups) : base(uowLookups)
{
UowLookups = uowLookups;
}
[HttpPost] //Improvise on this
[Route("getorderd")]
public IEnumerable<Department> GetSelectedValues(List<string> ids)
{
var sortColumns = new Dictionary<string, Sorter>();
sortColumns.Add("Code", new Sorter(1, SortDirection.Ascending));
sortColumns.Add("Name", new Sorter(2, SortDirection.Ascending));
IQueryable<Department> coll = Enumerable.Empty<Department>().AsQueryable();
var sortExp2 = ExpressionBuilder.OrderByColumns<Department>(coll, sortColumns);
var data = UowLookups.Repository<Department>().GetSelected(null, sortExp2 )
return data.ToList();
}
}
I have the following code (found in StackOverflow) that's working fine. But I want the following code to return (Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>
) instead of the collection. I also prefer not to pass the collection to this method, instead, it should take the TEntity
I pass as the collection. Is it doable?
public static IQueryable<TEntity> OrderByColumns<TEntity>(this IQueryable<TEntity> collection, IDictionary<string, Sorter> sortedColumns)
{
// Basically sortedColumns contains the columns user wants to sort by, and
// the sorting direction.
// For my screenshot, the sortedColumns looks like
// [
// { "cassette", { Order = 1, Direction = SortDirection.Ascending } },
// { "slotNumber", { Order = 2, Direction = SortDirection.Ascending } }
// ]
bool firstTime = true;
// The type that represents each row in the table
var itemType = typeof(TEntity);
// Name the parameter passed into the lamda "x", of the type TModel
var parameter = Expression.Parameter(itemType, "x");
// Loop through the sorted columns to build the expression tree
foreach (var sortedColumn in sortedColumns.OrderBy(sc => sc.Value.Order))
{
// Get the property from the TModel, based on the key
var prop = Expression.Property(parameter, sortedColumn.Key);
// Build something like x => x.Cassette or x => x.SlotNumber
var exp = Expression.Lambda(prop, parameter);
// Based on the sorting direction, get the right method
string method = String.Empty;
if (firstTime)
{
method = sortedColumn.Value.Direction == SortDirection.Ascending
? "OrderBy"
: "OrderByDescending";
firstTime = false;
}
else
{
method = sortedColumn.Value.Direction == SortDirection.Ascending
? "ThenBy"
: "ThenByDescending";
}
// itemType is the type of the TModel
// exp.Body.Type is the type of the property. Again, for Cassette, it's
// a String. For SlotNumber, it's a Double.
Type[] types = new Type[] { itemType, exp.Body.Type };
// Build the call expression
// It will look something like:
// OrderBy*(x => x.Cassette) or Order*(x => x.SlotNumber)
// ThenBy*(x => x.Cassette) or ThenBy*(x => x.SlotNumber)
var mce = Expression.Call(typeof(Queryable), method, types,
collection.Expression, exp);
// Now you can run the expression against the collection
collection = collection.Provider.CreateQuery<TEntity>(mce);
}
return collection;
}
Answer is simple:
public static Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> CreateOrderByFunc<TEntity>(IDictionary<string, Sorter> sortedColumns)
{
return q => (IOrderedQueryable<TEntity>)q.OrderByColumns(sortedColumns);
}