2012-11-21 7 views
8

返信レポートのソート順に複数のフィールドを選択できるレポートインターフェイスがあります。私が抱えている問題は、OrderBy/ThenByメソッドを実際にチェーンすることができないことです。ソートフィールドのリストを反復処理しているからです。LINQ/Entity Frameworkを使用してOrderBy/ThenByをプログラム的に連鎖させる

foreach (string sort in data.SortParams) 
{ 
    switch (sort) 
    { 
     case "state": 
      query = query.ThenBy(l => l.RegionCode); 
      break; 
     case "type": 
      query = query.ThenBy(l => l.Type); 
      break; 
     case "color": 
      query = query.ThenBy(l => l.Color); 
      break; 
     case "category": 
      query = query.OrderBy(l => l.Category); 
      break; 
    } 
} 

(注:私は、これは簡単にするための最初のソート項目であるかどうかを決定するスイッチを削除した)

コレクションを反復処理する方法上の任意の考え私はこのような何かを考えていますソート順を決定するには?

答えて

15

あなたが最初の「シード」のOrderBy使用する場合は、あなたがやりたいことができます:あなたが最初ThenBy句を取り付ける前IOrderedEnumerable(またはIOrderedQueryable)を作成するOrderByを呼び出す必要が

EDIT:

var orderedQuery = query.OrderBy(l => 0); 
foreach (string sort in data.SortParams) 
{ 
    switch (sort) 
    { 
     case "state": 
      orderedQuery = orderedQuery.ThenBy(l => l.RegionCode); 
      break; 
     case "type": 
      orderedQuery = orderedQuery.ThenBy(l => l.Type); 
      break; 
     case "color": 
      orderedQuery = orderedQuery.ThenBy(l => l.Color); 
      break; 
     case "category": 
      orderedQuery = orderedQuery.ThenBy(l => l.Category); 
      break; 
    } 
} 
query = orderedQuery; // cast back to original type. 

もっと柔軟にチェックアウトするにはthis answer

+0

クリエイティブですが、クエリのパフォーマンスに影響するかどうかを確認する必要があります。索引の使用を妨げる可能性があります。 – usr

+1

これは私の魅力のように働いた。最初は私は上記と全く同じコードを持っていましたが、最初の 'OrderBy()'のデフォルトの列を選択しなければなりませんでした。代わりに0を入れることはできませんでした。 0を指定すると、最終的なSQLクエリには、すべての行に対して値0を持つ追加の列が出てきて、その行で並べ替えてダミーのソートを行い、チェーンされた 'ThenBy() 'のすべての列を適用しますあなたが追加したものです。ありがとう! – BeemerGuy

+0

'OrderBy(l => 0)'を呼び出すときに 'ArgumentOutOfRangeException'が出ます。 [Here](https://pastebin.com/raw/TZQ9g8Es)は 'StackTrace'です。 – Shimmy

-1

1つのLinqクエリをすべて使用することは、可読性の観点から最良の選択肢ではありません。私はIQueryableを使用してメモリ内でクエリを構築します。同様の種類のswitch文を使用します(ただし、IQueryableを使用)。最後に.ToList(つまり列挙)を実行して、サーバで目的のクエリを実行します。

+1

ありがとうございますが、ここでは 'query' varは実際にはIQueryableです。問題はOrderByコマンドとThenByコマンドにあります。ThenByは、OrderByに最初にチェーンされている場合にのみ使用できるようです。 – acullen72

+1

ダウン票をexpalinケア!! ???????? – daehaai

1

私はこれらの拡張子を作成しました質問で述べたような方法は、同一の問題に取り組むために:これらの拡張メソッドだけで前の式をチェック

foreach (string sort in data.SortParams) 
{ 
    switch (sort) 
    { 
     case "state": 
      query = query.AppendOrderBy(l => l.RegionCode); 
      break; 
     case "type": 
      query = query.AppendOrderBy(l => l.Type); 
      break; 
     case "color": 
      query = query.AppendOrderBy(l => l.Color); 
      break; 
     case "category": 
      query = query.AppendOrderBy(l => l.Category); 
      break; 
    } 
} 

REMARK

public static class QueryableExtensions 
{ 
    public static IOrderedQueryable<T> AppendOrderBy<T, TKey>(this IQueryable<T> query, Expression<Func<T, TKey>> keySelector) 
     => query.Expression.Type == typeof(IOrderedQueryable<T>) 
     ? ((IOrderedQueryable<T>) query).ThenBy(keySelector) 
     : query.OrderBy(keySelector); 

    public static IOrderedQueryable<T> AppendOrderByDescending<T, TKey>(this IQueryable<T> query, Expression<Func<T, TKey>> keySelector) 
     => query.Expression.Type == typeof(IOrderedQueryable<T>) 
      ? ((IOrderedQueryable<T>)query).ThenByDescending(keySelector) 
      : query.OrderByDescending(keySelector); 
} 

問題のコードは、その後にリファクタリングすることができOrderByまたはThenByを使用するかどうかを判断するために、他の式は使用できません。もしそれに取り組もうとするなら、あなたは望んでいないオーバーヘッドを追加するかもしれない完全な木を歩かなければならないでしょう:)

関連する問題