2012-01-26 20 views
3

、拡張メソッドSelect()OrderBy()両方がとして定義されるObjectQuery、戻り:Select()の戻り型がIQueryable<T>でありOrderByのがIOrderedQueryable<T>あるObjectQueryは本当にIOrderedQueryableですか。エンティティ・フレームワークに適用

public class ObjectQuery<T> : ObjectQuery, IOrderedQueryable<T>, 
    IQueryable<T>, <... more interfaces> 

を。つまり、両方とも同じ型を返しますが、別のラッパーで返すと言うことができます。幸いなことに、の後にThenByを適用できるようになりました。

今、私の問題です。

var query = context.Plots.Where(p => p.TrialId == 21); 

これは私ObjectQuery<Plot>あるIQueryable<Plot>を与える:

さんが言ってみましょう私は、これは持っています。しかし、それはまたIOrderedQueryableです:

var b = query is IOrderedQueryable<Plot>; // True! 

しかし、それでもまだ:

var query2 = query.ThenBy(p => p.Number); // Does not compile. 
// 'IQueryable<Plot>' does not contain a definition for 'ThenBy' 
// and no extension method 'ThenBy' .... 

私が行うと:

var query2 = ((IOrderedQueryable<Plot>)query).ThenBy(p => p.Number); 

それはコンパイルが、実行時例外を与える:

タイプ 'IQueryable`1[Plot]'の式は使用できません。またはパラメータIOrderedQueryable`1[Plot] ThenBy[Plot,Nullable`1](IOrderedQueryable`1[Plot], Expressions.Expression`1[System.Func`2[Plot,System.Nullable`1[System.Int32]]])「メソッドの」タイプ'IOrderedQueryable`1[Plot]の「

キャストが(私がチェック)が行われるが、ThenByのパラメータは、まだ(私は少し困惑)のIQueryableとして見られています。

ここで、ObjectQuery<Plot>IQueryable<Plot>Select()など)として返されるとします。返されたオブジェクトのThenByに安全に呼び出すことができるかどうかを知りたければどうなりますか? ObjectQueryが「本当」か「偽」IOrderedQueryableの場合は、例外を捕まえずにどのように把握できますか?

+2

具体的な型をチェックすることをお勧めします。これは、クエリープロバイダにあなたを結びつけるもので、正確には 'IQueryable'が避けているものです。 1つのアプローチは、 'SortBy()'メソッドを調べるための式を素早く歩くことですが、誰かが何か簡単なことを指摘するだろうと思います。そうでない場合は、ここにコメントし、私はあなたに木を歩くためのコードを提供します。幸運 – Smudge202

+0

@ Smudge202ありがとうございました。表現木より歩くのがずっと楽しい場所がたくさんありますが、あなたが抵抗できなければ...しかし、はい、おそらく他の人。 –

+0

@ Smudge202 btw、両方のインタフェースを実装しているため、具体的な型をチェックするのは、とにかく動作しません。それは私が本当に知る必要がある場合、あなたが示唆するように、おそらく深い検査は唯一の方法であるので、ここでは通常の反射が役に立たないと私を困惑させる。 –

答えて

2

表現木は本当に楽しいです! (またはおそらく私はちょっと変わっている)Project Roslynが行くものなら、多くの開発者の将来に役立つでしょう! =)あなたの場合

、MSDNのExpressionVisitorからの単純な継承、およびSortBym.MethodInfoを比較するために何かを継承クラスでVisitMethodCallメソッドをオーバーライドします(あなたがしたい場合は、あまりにもうるさいじゃないすなわち場合は、単純に、名前を確認してください実際のSortBy MethodInfoと比較するために戸惑うことがある

ExpressionVisitorをコピーして貼り付けた後に正直言って、表現ツリーコード;-)

希望するもの

+0

あなたはそれをしました。あなたは私に表現樹ウイルスを感染させました!それは実行可能な解決策です(メソッド名は "OrderBy"です)。ただし、式に固有ですが、あなたが正しいとすれば、楽しいです!今のところ私の公園での散歩のために:)。これはここでもうまくいきましたが、純粋なC#用語で問題を明確にする質問を投稿します。 –

+0

興味がある人は:[ここ](http://stackoverflow.com/questions/9063131/how-to-tell-which-interface-is-returned-by-a-method)は、純粋なC#の質問です。 –

1

Expression Treesは楽しいですが、この場合、ThenByではなくOrderByを使用するという簡単な解決策はありませんか?

  • OrderByIQueryable上の拡張であり、IOrderedQueryableを返します。
  • ThenByは、IOrderedQueryableの拡張であり、IOrderedQueryableを返します。

ですから、(クエリがあるのIQueryable上記のあなたの場合、のように)のIQueryableを持っていて、それに最初の順序を適用したい場合は、OrderByを使用しています。 ThenByは、すでに順序付けられたクエリに追加の順序付けを適用することのみを目的としています。

static IOrderedQueryable<T, TKey> ApplyAdditionalOrdering<T, TKey>(this IOrderedQueryable<T, TKey> source, Expression<Func<T, TFilter>> orderBy) 
     { 
      return source.ThenBy(orderBy); 
     } 
:あなたはいくつかの種類のLINQの結果を持っていますが、あなたはそれが IQueryableIOrderedQueryableであるかどうかわからないですし、それに追加のフィルタリングを適用したい場合は

、次のような2つのメソッドを作ることができます

そして

static IOrderedQueryable<T, TKey> ApplyAdditionalOrdering<T, TKey>(this IQueryable<T> source, Expression<Func<T, TFilter>> orderBy) 
     { 
      return source.OrderBy(orderBy); 
     } 

コンパイラは、クエリオブジェクトのコンパイル時の型に基づいて呼び出すために正しいものを把握します。

+0

それは賢明な解決策です。 1つの欠点は、* inside *とexpressionに使用できません。その間、IQueryableに初期ソートがあるかどうかを知る必要は全くありませんでした。私はこのノーオペレーションのインターフェースに困惑していただけでした。 –

関連する問題