2011-08-08 14 views
1

私はLINQ(C#)でOrder要素のテーブルをクエリしています。各注文には次のフィールドがあります。LINQ - 複雑な並べ替え

- ID 
- OpenDate 
- PriorityID 
- StatusID 
- Description 

StatusIDフィールドはステータステーブルにマップします。私は彼らの優先順位やステータスによって並べ替えOrderオブジェクトのすべてを取得する必要があり

- ID 
- Name 

:ステータステーブルは次のように構成されています。 Orderオブジェクトを正常にソートできるようになりました。私は、次の を経由して、これをやっている:

List<Order> orders = new List<Order>(); 
using (DBDataContext context = new DBDataContext()) 
{ 
    orders = (from o in context.Orders 
      orderby (o.PriorityID.HasValue ? o.PriorityID : Int32.MaxValue) ascending 
      select o).ToList(); 
} 

しかし、私の問題は、状況を加味しています。

注文オブジェクトが優先度でソートされたら、注文オブジェクト を、ステータス:キャンセル、オープン、ルート内、および配信の順にソートする必要があります。重要: これらのステータス値のIDは、ランダムで役立たない順序でしっかりと設定されています。私はそれらを変更することはできません。あなたが分かるように、アルファベット名でステータスをソートすることはできません。また、データベースにフィールドを追加することはできません。誰も私がLINQでこの問題を解決できる方法を教えてもらえますか?

ありがとうございました!

+1

こちらもトップ(テイク)を取っていますか? DBで処理する必要があるのか​​、それとも.NETコードでソートできるのか不思議です... –

+0

はい、ソートする必要がある項目はいくつですか?クライアントサイドで行うことができるのであれば、IComparerまたはComparisonデリゲート 'List.OrderBy(x、y => ...)'は十分です。 –

+0

フロントエンドのOrderクラスに計算フィールドを追加できますか?その後、そのフィールドでソートすることができます。次のようなものがあります: "select new {SortField =ここでソートインデックスを計算}" – Andrei

答えて

2

私はあなたがこの解決策を持っていると思いますIComparerを実装し、Linqを使用して注文します。あなたのステータスは数値でもアルファベットでもないからです。

その後、
public class CustomComparer : IComparer<Status> 
{ 
    public int Compare(Status statusA, Status statusB) 
    { 
     if (statusA.StatusName == "Cancelled" && statusB.StatusName == "Cancelled") 
     { 
      return 0; // equals 
     } 
     else if (statusA.StatusName == "Cancelled" && statusB.StatusName != "Cancelled") 
     { 
      return 1; // A > B 
     } 
     .... 
    } 
} 

orders.OrderBy(x => x.Status, new CustomComparer()) 

この情報がお役に立てば幸いです。

+0

シーケンスの順序が非常に限定的で、変更されるか、後で新しい項目が追加されるため、ifsの代わりにswitch-caseステートメントを記述します。 – Andrei

+0

私はこのアプローチが好きです。しかし、次の行を実行すると、 "クエリ演算子 'ThenBy'に使用されているサポートされていないオーバーロードが発生しました:var results = context.Orders.OrderBy(p => p.PriorityID ?? Int32.MaxValue).ThenBy => s.StatusID、新しいCustomComparer())。ToList(); – user609886

+0

おそらくそれはSQLとして表現できないからです。あなたは配列内の命令をキャッシュしておき、ソートを適用することができます(パフォーマンス上の理由から、やりとりすることはできません) – FuleSnabel

0

ステータスのリストが一致する限り、 "COID"などの文字列を作成し、 "COID" .indexOf(firstletterofstatus)に基づいて2つのステータスを比較できます。最高のソフトウェアの習慣ではないかもしれませんが、うまくいくでしょう。

-1

それは長いリスト(すなわち、それはメモリ内に合理的にフィットする)ことはないだろう場合は、ステータスと相対次数間のマッピングを使用してクライアント側を並べ替えることができます:

int StatusOrder(Status status) 
{ 
    switch(status.Id) 
    { 
     case 1: return 5; 
     case 2: return 1; 
     case 4: return 3; 
     //etc 
    } 
} 

List<Order> orders; //no need to create a list here 
using (DBDataContext context = new DBDataContext()) 
{ 
    orders = (from o in context.Orders 
     orderby (o.PriorityID.HasValue ? o.PriorityID : Int32.MaxValue) ascending, 
       SorderOrder(o.Status) 
     select o).ToList(); 
} 
+0

-1: 'StatusOrder'をSQLに変換できないため、実行時例外が発生します。 –

関連する問題