私は自分の会社用のアプリを書いており、現在検索機能に取り組んでいます。ユーザーがアイテムを検索するときに、最新のバージョン(データベースに保存されているバージョン)を表示したいと思います。
問題は、バージョンがintではなく文字列として保存され、結果に対してOrderBy(q => q.Version)を実行すると、次のように返されることです。
1
10
11
2
3
...
明らかに2は10の前に来ます。
バージョンを整数としてキャストする方法はありますか、それとも単純なIComparerがありますか?これまでのところ、実質的なものは何も見つかりませんでした。
私はこれをやってみました:
var items = (from r in results
select r).OrderBy(q => Int32.Parse(q.Version));
これはコンパイルされますが動作しません。
Int32.Parseは、LinqToSqlトランスレータではサポートされていません。 Convert.ToInt32がサポートされています。
あなたの問題はどこかにあります、次の作品:
new[] { "1", "10", "2", "3", "11" }
.OrderBy(i => int.Parse(i))
.ToList()
.ForEach(Console.WriteLine);
問題がLINQ to SQLの場合、CLRがLINQからSQLを作成しようとしており、int.Parse
を理解できません。あなたができることは、最初にSQLからデータを取得し、すべてのデータがロードされたらそれを注文することです:
var items = (from r in results
select r)
.ToList()
.OrderBy(q => Int32.Parse(q.Version));
それを行う必要があります。
テーブル定義を変更できず(バージョンが数値型であるため)、クエリが実際にリストされているとおりである(スキップ、テイク、またはその他の方法で結果の数を減らしていない)場合、最善の方法並べ替えられていない結果に対して "ToList"を呼び出します。これにより、OrderBYラムダを適用すると、SQL Server側で実行するのではなく、コードで実行されます(これで機能するはずです)。
なぜラムダでソートするのですか?クエリを並べ替えてみませんか?
var query = from r in items
orderby int.Parse( r )
select r;
LINQ to SQLを使用していることがわかったので、次のような方法で標準のSQL呼び出しを行うことを検討してください。
Select ..., Cast( TextWhichShouldBeIntCol As int ) As IntCol
From ...
あるいは
Select ..., Cast( TextWhichShouldBeIntCol As int ) As IntCol
From ...
Order By Cast( TextWhichShouldBeIntCol As int )
これは、intとしてLINQに流れ込みます(2番目の反復を使用する場合は、順序付けされます)。これにより、LINQで結果セットを2回実行する必要がなくなります(クエリの場合は1回、順序付けの場合は1回)。
自然な並べ替えに関しては、すばらしい仕事をする素晴らしいコードがあります。その名前は AlphanumComparator
。
サンプルコード:
var ordered = Database.Cars.ToList().OrderBy(c => c.ModelString, new AlphanumComparator());
リストはメモリ内になければならないことに注意してください。
C#バージョンを取得した場合は、次のようにします。
AlphanumComparator : IComparer<string>
そして
public int Compare(string x, string y)
var items = (from r in results
select r).OrderBy(q => Convert.ToInt32(q.Version));
間違いなく実行......
テストをしました。次のコードがあります。
_string[] versions = { "1", "2", "10", "12", "22", "30" };
foreach (var ver in versions.OrderBy(v => v))
{
Console.WriteLine(ver);
}
_
予想通り、結果は1、10、12、2、22、30になります。次に、versions.OrderBy(v => v))
をversions.OrderBy(v => int.Parse(v)))
に変更します。そしてそれはうまくいきます:1、2、10、12、22、30
あなたの問題は、あなたの文字列に '。'のような数字でない文字が含まれていることだと思います。どのような例外がありますか?
「最新バージョン」だけが必要なのに、なぜソートするのですか? Max()を使用すると、オーバーヘッドを回避できるようです。
また、列のタイプを整数に変更する必要があります。
これを試して:
var items = results.(Select(v => v).OrderBy(v => v.PadLeft(4));
それはLinq2Sqlで動作します
数値ではなくテキスト値があるようです。
並べ替える必要がある場合は、次のことを試してください。
var items = (from r in results
select r);
return items.OrderBy( v=> Int.Parse(v.Version) );
var query = from r in items
let n = int.Parse(r)
orderby n
select n;
var items = (from v in results
select v).ToList().OrderBy(x => int.Parse(x.Version));