表达式 OrderBy Then 通过返回 (Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>)
Expression OrderBy Then By returning (Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>)
我有一个存储库 class 如下。我的问题出在 GetSelected 方法
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();
}
}
}
我正在尝试通过提供如下参数来对部门进行排序。
[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();
}
}
我有以下代码(在 Whosebug 中找到)运行良好。但是我想用下面的代码return(Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>
)代替集合。我也不希望将集合传递给此方法,相反,它应该将我传递的 TEntity
作为集合。可行吗?
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;
}
答案很简单:
public static Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> CreateOrderByFunc<TEntity>(IDictionary<string, Sorter> sortedColumns)
{
return q => (IOrderedQueryable<TEntity>)q.OrderByColumns(sortedColumns);
}
我有一个存储库 class 如下。我的问题出在 GetSelected 方法
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();
}
}
}
我正在尝试通过提供如下参数来对部门进行排序。
[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();
}
}
我有以下代码(在 Whosebug 中找到)运行良好。但是我想用下面的代码return(Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>
)代替集合。我也不希望将集合传递给此方法,相反,它应该将我传递的 TEntity
作为集合。可行吗?
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;
}
答案很简单:
public static Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> CreateOrderByFunc<TEntity>(IDictionary<string, Sorter> sortedColumns)
{
return q => (IOrderedQueryable<TEntity>)q.OrderByColumns(sortedColumns);
}