Linq-to-Entities动态排序

这是我的查询,如何使用string作为orderby参数?

string sortColumn="Title"; var items = (from ltem in ctxModel.Items where ltem.ItemID == vId orderby //something here select ltem).Skip(PageSize * PageIndex).Take(PageSize); 

更新:
我不能只是OrderBy的结果集,因为我首先需要排序,只有THEN才能进行分页。

其他人建议使用动态链接或其他库。 就个人而言 ,我不会为这么小的任务带来库依赖。 但是你可以采取另外两条路径……

  • 使用对象调用语法并动态构建查询表达式树。 例如…

见http://blog.cincura.net/229310-sorting-in-iqueryable-using-string-as-column-name/

在此方案中考虑延迟执行很重要。 您可以安全地构建返回IQueryable对象的查询,然后对该对象运行对象查询排序。 只有在实际访问数据时,您的查询才会运行一次。

上面的博客文章是一个示例,说明如何使用Expression API构建可用于OrderBy的表达式树。 这听起来真的很复杂。 MSDN文章可能是更好的参考。 请参见如何:使用表达式树在MSDN上构建动态查询 。

要么

  • 使用简单路由,只需在整个查询的标题上使用开关即可。

例如。

 ItemType items = default(ItemType); switch(sortColumn) { case "Title": { items = ctxModel.Items .Where(i => i.ItemID == vId) .OrderBy( i => i.Title); } break; } 

我用这个帮手:

 public static class OrderExt { private static IOrderedQueryable Order(this IQueryable source, string propertyName, SortDirection descending, bool anotherLevel = false) { var param = Expression.Parameter(typeof(T), string.Empty); var property = Expression.PropertyOrField(param, propertyName); var sort = Expression.Lambda(property, param); var call = Expression.Call( typeof (Queryable), (!anotherLevel ? "OrderBy" : "ThenBy") + (descending == SortDirection.Descending ? "Descending" : string.Empty), new[] {typeof (T), property.Type}, source.Expression, Expression.Quote(sort)); return (IOrderedQueryable)source.Provider.CreateQuery(call); } } 

调用助手,例如这样做:

 string sort = HttpContext.Current.Request.QueryString["sort"]; var products = _productRepository.OrderBy(sort, SortDirection.Ascending); 

这是另一种选择, EntitySorter 。 允许动态LINQ对字符串执行的操作,但将操作包装在对象中,就像使用查询对象模式一样 。 它允许按字符串排序和类型安全结构。 这里有些例子:

 // Ways of defining an entity sorter // 1. Using strings: IEntitySorter sorter = EntitySorter .OrderBy("Address.City") .ThenByDescending("Id"); // 2. Defining a sorter with lambda's IEntitySorter sorter = EntitySorter .OrderByDescending(p => p.Name) .ThenBy(p => p.Id) .ThenByDescending(p => p.Address.City); // 3. Using a LINQ query IEntitySorter sorter = from person in EntitySorter.AsQueryable() orderby person.Name descending, person.Address.City select person; // And you can pass a sorter from your presentation layer // to your business layer, and you business layer may look // like this: static Person[] GetAllPersons(IEntitySorter sorter) { using (var db = ContextFactory.CreateContext()) { IOrderedQueryable sortedList = sorter.Sort(db.Persons); return sortedList.ToArray(); } } 

你可以在这里找到代码。

显然, Dynamic Linq的其他暗示还不够明确。 让我说清楚..

使用Dynamic Linq并不一定表示需要汇编依赖。

动态Linq包含在一个源文件中,如果我没有记错的话,它包含在C#示例中,每个人都应该至少在过去3年的某个时间看过,并且可以轻松地放入项目和命名空间以防止冲突,从而提供可在需要时使用的表达式构建服务。

我认为能够从一个合理的任意string安全地构造一个表达式,这个string可以很容易地动态构建,成为“动态”的最好例子。

考虑:

  var query = northwind.Products .Where("CategoryID = 3 AND UnitPrice > 3") .OrderBy("SupplierID"); 

该查询看起来像是在使用自定义数据绑定和/或ObjectDataSource,无论如何,有一种方法可以使用扩展方法来执行此操作,该方法采用排序表达式并动态地将orderBy()调用(表达式)附加到linq查询。 我记录了博客在一段时间后发布的内容,巧合的是这个SO问题的一部分。 如果你需要更多,你可以使用动态linq ,scottgu 很好地记录了它。

编辑:使用扩展方法会使它看起来像

 string sortColumn="Title"; var items = (from ltem in ctxModel.Items where ltem.ItemID == vId select ltem).Skip(PageSize * PageIndex).Take(PageSize).OrderBy(sortColumn);