Linq-to-Entities动态排序

时间:2010-04-30 19:29:48

标签: c# linq entity-framework

这是我的查询,如何使用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结果集,因为我 FIRST 需要排序,只有 THEN 才能进行分页。

5 个答案:

答案 0 :(得分:13)

我使用这个助手:

public static class OrderExt
{
    private static IOrderedQueryable<T> Order<T>(this IQueryable<T> 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<T>)source.Provider.CreateQuery<T>(call);
    }
}

调用助手,例如:

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

答案 1 :(得分:8)

这是另一种选择,EntitySorter。允许动态LINQ对字符串执行的操作,但将操作包装在对象中,就像使用Query Object pattern一样。它允许按字符串排序和类型安全构造。以下是一些例子:

// Ways of defining an entity sorter
// 1. Using strings:
IEntitySorter<Person> sorter = EntitySorter<Person>
    .OrderBy("Address.City")
    .ThenByDescending("Id");

// 2. Defining a sorter with lambda's
IEntitySorter<Person> sorter = EntitySorter<Person>
    .OrderByDescending(p => p.Name)
    .ThenBy(p => p.Id)
    .ThenByDescending(p => p.Address.City);

// 3. Using a LINQ query
IEntitySorter<Person> sorter =
    from person in EntitySorter<Person>.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<Person> sorter)
{
    using (var db = ContextFactory.CreateContext())
    {
        IOrderedQueryable<Person> sortedList =
            sorter.Sort(db.Persons);

        return sortedList.ToArray();
    }
}

您可以找到代码here

答案 2 :(得分:6)

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

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

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

在这种情况下考虑Deferred Execution很重要。您可以安全地构建返回 IQueryable 对象的查询,然后对该对象运行对象查询排序。只有在实际访问数据时,您的查询才会运行一次。

以上博客文章是一个示例,说明如何使用Expression API构建和表达树,您可以将其用于 OrderBy 。这听起来真的很复杂。 MSDN文章可能是更好的参考。请参阅MSDN上的How to: Use Expression Trees to Build Dynamic Queries

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

例如

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

答案 3 :(得分:4)

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

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

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

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

考虑:

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

答案 4 :(得分:1)

该查询看起来像是在使用自定义数据绑定和/或ObjectDataSource,无论如何,有一种方法可以使用扩展方法来执行此操作,该方法采用排序表达式并动态地将一个OrderBy()调用(表达式)附加到linq查询。我记录了blog post一段时间后的情况,这恰好是this SO question的一部分。如果您需要更多,可以使用scottgu的{em> dynamic linq documented pretty well

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

string sortColumn="Title";

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