sort - vb.net linq order by




LINQの複数の「注文」 (5)

DataContextの次の行を使用して、DataContextのSQLアクティビティをコンソールに記録します。次に、linq文がデータベースから要求しているものを正確に見ることができます。

_db.Log = Console.Out

次のLINQステートメント:

var movies = from row in _db.Movies 
             orderby row.CategoryID, row.Name
             select row;

そして

var movies = _db.Movies.OrderBy(m => m.CategoryID).ThenBy(m => m.Name);

次のSQLを生成します。

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].CategoryID, [t0].[Name]

一方、LinqでOrderByを繰り返すことは、結果のSQL出力を逆転させるようです。

var movies = from row in _db.Movies 
             orderby row.CategoryID
             orderby row.Name
             select row;

そして

var movies = _db.Movies.OrderBy(m => m.CategoryID).OrderBy(m => m.Name);

次のSQLを生成します(NameとCategoryIdが切り替わります)。

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].[Name], [t0].CategoryID

私は2つのテーブル、 moviescategoriesを持っていcategories 。そして、私はcategoryID順で 、次に名前で順序付けられたリストを取得します

ムービーテーブルには、 ID、Name、およびCategoryIDの 3つの列があります 。 カテゴリテーブル2には、列IDと名前があります。

私は次のようなものを試しましたが、うまくいきませんでした。

var movies = _db.Movies.OrderBy( m => { m.CategoryID, m.Name })

IQueryableがすでに注文されているかどうか心配する必要がないように、いくつかの拡張メソッドを作成しました(下記)。 複数のプロパティで注文する場合は、次のようにします。

// We do not have to care if the queryable is already sorted or not. 
// The order of the Smart* calls defines the order priority
queryable.SmartOrderBy(i => i.Property1).SmartOrderByDescending(i => i.Property2);

これは、ソートするプロパティのリストから動的に順序を作成する場合に特に役立ちます。

public static class IQueryableExtension
{
    public static bool IsOrdered<T>(this IQueryable<T> queryable) {
        if(queryable == null) {
            throw new ArgumentNullException("queryable");
        }

        return queryable.Expression.Type == typeof(IOrderedQueryable<T>);
    }

    public static IQueryable<T> SmartOrderBy<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable<T>;
            return orderedQuery.ThenBy(keySelector);
        } else {
            return queryable.OrderBy(keySelector);
        }
    }

    public static IQueryable<T> SmartOrderByDescending<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable<T>;
            return orderedQuery.ThenByDescending(keySelector);
        } else {
            return queryable.OrderByDescending(keySelector);
        }
    }
}

新しく追加する":

var movies = _db.Movies.OrderBy( m => new { m.CategoryID, m.Name })

それは私の箱で働く。 ソートに使用できるものを返します。 2つの値を持つオブジェクトを返します。

類似していますが、以下のように、結合列によるソートとは異なります。

var movies = _db.Movies.OrderBy( m => (m.CategoryID.ToString() + m.Name))

最も簡単な方法ではありませんが、LINQを使用してこれを行う方法は少なくとももう1つあります。 これは、 IComparerを使用するOrberBy()メソッドを使用して行うことができIComparer 。 最初に、次のようにMovieクラスのIComparerを実装する必要がありIComparer

public class MovieComparer : IComparer<Movie>
{
    public int Compare(Movie x, Movie y)
    {
        if (x.CategoryId == y.CategoryId)
        {
            return x.Name.CompareTo(y.Name);
        }
        else
        {
            return x.CategoryId.CompareTo(y.CategoryId);
        }
    }
}

次に、次の構文で映画を注文することができます:

var movies = _db.Movies.OrderBy(item => item, new MovieComparer());

アイテムの1つを降順に切り替える必要がある場合は、 MovieComparer応じてMovieComparer Compare()メソッド内のxとyを切り替えます。


非ラムダのクエリ構文LINQを使用すると、これを行うことができます:

var movies = from row in _db.Movies 
             orderby row.Category, row.Name
             select row;

[EDIT to comment comment]ソート順を制御するには、キーワードascending (デフォルトであり、特に有用ではない)またはdescendingのキーワードを使用します。

var movies = from row in _db.Movies 
             orderby row.Category descending, row.Name
             select row;




sql-order-by