1

データベース検索の実行中に、文字列の値から最初の文字を引いた値でリストを並べ替えるにはどうすればよいですか (私の場合、最初の文字は常に C の後に数字が続きます)。

私は多くのことを試しましたが、暗闇の中でほとんどつまずいています。ここの誰かがこれをすぐに解決できると確信しています.

動作する私のコード(しかし、私が望むことはしません):

        List<Customer> customerlist = null;
        try
        {
            customerlist = db.Customers
                            .Where(u => (u.Cust_ID+u.Given_Name+u.Surname).Contains(searchstring))
                            .OrderBy(u => u.Cust_ID)
                            .ToList();
        }

現時点での私のバグのあるコード (動作するはずですが、検索では常に結果が返されません):

        List<Customer> customerlist = null;
        try
        {
            customerlist = db.Customers
                            .Where(u => (u.Cust_ID+u.Given_Name+u.Surname).Contains(searchstring))
                            .OrderBy(u => Int32.Parse(u.Cust_ID.TrimStart('C')))
                            .ToList();
        }

詳細:

テーブルに Cust_ID という名前の列があります。この列は C で始まり、その後に C1、C2、... C43、... C999 などの先行ゼロのない数字が続きます。

ユーザーが検索を実行できるようにしています。そのクエリは searchstring に割り当てられています。

int パースを削除してデバッグを試みました

                            .OrderBy(u => u.Cust_ID.TrimStart('C'))

それも結果を返しません。

ここにある元のコードは、検索を完了するために引き続き機能しますが、正しくソートされません。

                            .OrderBy(u => u.Cust_ID)

TrimStart の代わりに Replace を使用してみました

                            .OrderBy(u => u.Cust_ID.Remove(0, 1))

そして、これは結果を返しますが、まだソートしません.Int解析を入れると、再び結果を返すのをやめます:

                            .OrderBy(u => Int32.Parse(u.Cust_ID.Remove(0, 1)))

int パースを次のように切り替えてみました。

                            .OrderBy(u => int.Parse(u.Cust_ID.Remove(0, 1)))

しかし、それは役に立ちませんでした。

編集:例外が発生していることがわかりました:

System.NotSupportedException: LINQ to Entities does not recognize the method 'Int32 ToInt32(System.String)' method, and this method cannot be translated into a store expression.
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
       at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
       at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
       at System.Data.Objects.ELinq.ExpressionConverter.Convert()
       at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
       at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
       at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       at lab2.Controllers.DemoController.retrievecustomers() in [[Directory]]Controller.cs:line 52
4

5 に答える 5

2

AsEnumerableに LINQ to Objects に切り替えるために使用できます。言い換えれば、ORM の試行 (いわば失敗) を SQL の ORDER BY にマップさせる代わりに、クライアント側で実行することになります。 OrderByOrderBy

そうは言っても、変更されないプレフィックスをデータベースに保存するのは悪い考えです。スペースを浪費し、誤ったデータ型 (INT ではなく VARCHAR) を使用するように強制し、ORDER BY で間違った種類の比較をトリガーし、ORDER BY がインデックスを使用できないようにします (ただし、WHERE は既にそれを行うのに非常に効果的です)。 .

于 2012-08-24T02:04:15.537 に答える
1

クライアント側で注文するだけです。なんで?ネットワークを通過するトラフィックの量が増加せず、柔軟性が大幅に向上し、危険な値をチェックできるようになるためです。サーバーの負荷を軽減するため、とにかくクライアントでソートを行う方が良いと主張することができます.

customerlist = db.Customers
    .Where(u => (u.Cust_ID+u.Given_Name+u.Surname).Contains(searchstring))
    .AsEnumerable()  //EDIT: was ToArray()
    .OrderBy(u => Int32.Parse(u.Cust_ID.SubString(1)))
    .ToList();

AsEnumerable により、その時点までの linq クエリがサーバーに送信され、その後のすべてがクライアントで行われることに注意してください。

補足として、リストを変更する必要がない場合は、リストではなく配列に値を格納する方がわずかに効率的であることを付け加えておきます。

また、検索のために名前を付けて CustID に本当に参加しますか? これにより、Bob という検索用語が Bo Brown という人物と一致することになります。

編集: ToArray を AsEnumerable に変更しました。Branko Dimitrijevic が指摘したように、これはより効率的です。他の回答から一部を引用することが非倫理的である場合は、申し訳ありません。

于 2012-08-24T02:03:21.380 に答える
0

LINQについてはよくわかりませんが、これを試してください

.OrderBy(u => Convert.ToInt32(u.Cust_ID.Substring(1)))
于 2012-08-24T00:54:37.777 に答える
0

私の推測では、データベースに「C [0-9] +」の形式ではなく、int.Parseと互換性がなく、おそらく「null」の値が含まれているため、OrderByで例外が発生します。

于 2012-08-24T00:59:09.727 に答える
0

データをプルした後に並べ替えを行うことができるという MikeKulls に同意しますが、サーバー上で並べ替えを行う場合は、文字列をパディングして整数並べ替えのセマンティクスを取得できます。

customerlist = db.Customers
                .Where(u => (u.Cust_ID+u.Given_Name+u.Surname).Contains(searchstring))
                .OrderBy(u => u.Cust_ID.Substring(1).PadLeft(10 /* or suitable number */, '0'))
                .ToList();
于 2012-08-24T02:38:52.890 に答える