0

思い通りに並べられていない linq クエリがあります。

クエリ:

return (from obj in context.table_orders
    orderby obj.order_no
    select obj.order_no.ToString() + '-' + obj.order_description).ToList<string>();

私のレコードはアルファベット順に並べられていますが、レコードが正しく並べ替えられるように使用できる Linq キーワードはありますか (したがって、注文 30 は注文 100 の前になります)。

これは ComboBox への入力に使用されるため、結果を文字列のリストにしたいと考えています。

また、DB の「order_no」の一部は「2.10」や「9.1.1」などです。

4

5 に答える 5

3

私のレコードはアルファベット順に並べられていますが、レコードが正しく並べ替えられるように使用できる Linq キーワードはありますか (したがって、注文 #30 は注文 #100 より前になります)。

誰かがこれを尋ねるたびに 1 セントもらえたら、私は金持ちになります。

はい、あります - 簡単な答え: 文字列ではなく数字を注文してください。

したがって、注文 #30 は注文 #100 の前に来ます)

しかし、#30 は #100 の後に来ます。単純な理由は、文字列であるためアルファベット順にソートされているからです。

文字列を解析し、数値を数値に変換し、それによって並べ替えます。

order_no が固定長 (00030 など) のない文字列であるべきだという考えを持っていた人は誰でも、データベース モデリングに関する基本的な教育を受ける必要があります。私は請求書番号などを文字列にするのが好きです (数字ではありません) が、(a) 防御可能なパターンと (b) チェックサム (データ入力エラーを簡単に見つけられるようにするため) で維持することが基本です;)

これは、データベースとデータ モデルを定義し、その結果について考えていない経験の浅い人が直面する問題です。

あなたはいくつかの苦痛に苦しんでいます - 文字列を解析し、解析結果の順に並べます。

于 2012-05-24T19:36:05.333 に答える
0

あなたが言ったことに基づいて-数字は実際には数字ではなく、カスタムシーケンス識別子です(つまり、どのレベルの深さを取得するかさえわかりません)カスタム比較機能を実装することをお勧めします。

これを行うと、あなたはあなたが望むものを定義することができます-そしてそれは私がこれらの線に沿って何かを信じています:

  • 文字列を分割します.
  • 短いシーケンスのarray.lengthまでのシーケンスを比較します
  • 短いシーケンスがあり、今までに同点がある場合は、長い前に短いものを選択します(つまり、2.1前に2.1.1
  • 両方のシーケンスの長さが同じである場合、比較の終わりまでに、どちらが「大きい」かを知る必要があります。
  • 解決しました。

IComparer以下の例の実装に関するインスピレーションが必要な場合:http:
//zootfroot.blogspot.co.uk/2009/09/natural-sort-compare-with-linq-orderby.html

于 2012-05-24T20:14:30.893 に答える
0

可能であればデータ型を変更するか、該当する場合は別のフィールドとして追加します。それがうまくいかない場合は、この質問で他の人が言及した解決策を見ることができますが、注意してください- .ToList() オプションは、小さなテーブルからすべてを引き出す場合に適していますが、慣れると最終的には痛みの世界。長期的にはすべてを取得する必要はありません。Where または上位の基準を使用してください。

他のソリューションは素晴らしいですが、タスクを達成するには私の好みでは複雑です。

LinqToSql を介して直接 SQL を撮影することができます。http://msdn.microsoft.com/en-us/library/bb399403.aspx

SQL では、好きなように自由に変換およびソートできます。これは素晴らしいアイデアだと思う人もいれば、悪いと言う人もいます。強いタイピングを失い、パフォーマンスが向上します。なぜこの種の決定を下すのかを知る必要があります。それが最も重要なことです。

于 2012-05-24T20:21:50.100 に答える
0

SQL に変換可能なカスタム orderby 関数を思いついた人は誰もいなかったので、次のように IComparer 関数を使用しました。

    public class OrderComparer<T> : IComparer<string>
    {
        #region IComparer<string> Members

        public int Compare(string x, string y)
        {
            return GetOrderableValue(x.Split('-').First()).CompareTo(GetOrderableValue(y.Split('-').First()));
        }
        #endregion

        private int GetOrderableValue(string value)
        {
            string[] splitValue = value.Split('.');
            int orderableValue = 0;
            if (splitValue.Length.Equals(1))
                orderableValue = int.Parse(splitValue[0]) * 1000;
            else if (splitValue.Length.Equals(2))
                orderableValue = int.Parse(splitValue[0]) * 1000 + int.Parse(splitValue[1]) * 100;
            else if (splitValue.Length.Equals(3))
                orderableValue = int.Parse(splitValue[0]) * 1000 + int.Parse(splitValue[1]) * 100 + int.Parse(splitValue[2]) * 10;
            else
                orderableValue = int.Parse(splitValue[0]) * 1000 + int.Parse(splitValue[1]) * 100 + int.Parse(splitValue[2]) * 10 + int.Parse(splitValue[3]);

            return orderableValue;
        }
    }

値は最大 4 レベルです。誰もが推奨を持っていますか?

于 2012-05-24T20:39:59.507 に答える
0

が文字列の場合obj.order_noは、並べ替えのために数値に変換します

orderby Int32.Parse(obj.order_no)

また

orderby Decimal.Parse(obj.order_no)

これは、文字列が有効な数値を表している場合にのみ機能します。


order_noが有効な数値でない場合(例: "17.7-8A")、右揃えの数値を含むように書式設定する関数を記述します。"00017.007-0008A"この関数を使用してソートします

orderby FormatOrderNo(obj.order_no)

アップデート

EF を使用しているため、クエリの EF 部分でこの関数を呼び出すことはできません。EF 結果を に変換し、IEnumerable<T>LINQ-To-Objects を使用して並べ替えを実行します。

return (from obj in context.table_orders select ...)
    .AsEnumerable()
    .OrderBy(obj => FormatOrderNo(obj.order_no))
    .ToList();
于 2012-05-24T19:37:46.473 に答える