13


12

以下は、同じデータを返す2つのクエリです。 それ以外のスタイル私はどちらが良いかわからない。

これらのクエリに影響を与える要因は何ですか? あるスタイルを他のスタイルよりも使用する利点は何ですか?

サンプル1

var x = from s db.Surveys sq = s.IDのsq.Survey_ID join q = sq.Question_ID = q.ID join qg in db.Question_Groups on q.ID Question_IDここでs.Type_ID.Equals(typeID)

サンプル2

var x = db.Surveys.Where(s => s.Type_ID.Equals(typeID)

8 Answer


21


更新日:あなたはあなたの肩書きを修正しました、それで暴言を無視します

質問のタイトルは、コードサンプルとは関係ありません。 あなたの質問は、一方の構文がIEnumerableで他方がIQueryableであることを暗示していますが、これは誤りです。 サンプルで、 `+ db.Surveys +`がIQueryableである場合、サンプルは_both_ IQueryableを使用しています。 私は両方の質問に答えようとします。

あなたの2つのコードサンプルは、同じLINQクエリを書くための異なる方法です(それらがよく書かれていると仮定して)。 サンプル1のコードは、サンプル2のコードの略記です。 コンパイラは両方のサンプルのコードを同じ方法で扱います。 C#コンパイラが `+ int?`を ` Nullable +`と同じように扱う方法を考えてください。 C#とVB.Netの両方の言語で、この省略形のクエリ構文が提供されています。 他の言語ではこの構文が使用されていない可能性があり、サンプル2の構文を使用する必要があります。 実際、他の言語では拡張メソッドやラムダ式さえもサポートされていない可能性があり、あなたはまだもっと曖昧な構文を使わなければならないでしょう。

'' '' '

更新:

Sanderの例をさらに詳しく言うと、次のように書くと(クエリ理解構文)

var surveyNames = from s in db.Surveys select s.Name

あなたは、コンパイラがその短縮形を以下のように考えます(拡張メソッドとラムダ式)。

IQueryable surveryNames = db.Surveys.Select(s => s.Name);

しかし、実際には拡張メソッドとラムダ式はそれ自体が省略形です。 コンパイラは次のようなものを出力します(正確にではなく、単にアイデアを与えるために)。

Expression> selector = delegate(Survey s) { return s.Name; };
IQueryable surveryNames = Queryable.Select(db.Surveys, selector);

`+ Select()`は ` Queryable +`クラスの単なる静的メソッドであることに注意してください。 あなたの.NET言語が問い合わせ構文、ラムダ、または拡張メソッドをサポートしていなかったなら、それはちょっとあなた自身がコードを書かなければならないだろう方法です。

'' '' '

_ あるスタイルを他のスタイルよりも使用する利点は何ですか? _

小さなクエリでは、拡張メソッドはよりコンパクトになります。

var items = source.Where(s => s > 5);

また、拡張メソッドの構文は、条件付きのwhere句など、より柔軟性があります。

var items = source.Where(s => s > 5);

if(smallerThanThen)
    items = items.Where(s => s < 10);
if(even)
    items = items.Where(s => (s % 2) == 0);

return items.OrderBy(s => s);

さらに、いくつかのメソッドは拡張メソッドの構文(Count()、Aggregate()、Take()、Skip()、ToList()、ToArray()など)を介してのみ利用可能です。両方の構文が混在しないように、通常はこの構文でクエリ全体を記述します。

var floridaCount = source.Count(s => s.State == "FL");

var items = source
            .Where(s => s > 5)
            .Skip(5)
            .Take(3)
            .ToList();

一方、クエリがより大きく複雑になると、特にいくつかの「+ let 」、「 group 」、「 join +」などで複雑になり始めると、クエリの理解構文がより明確になります。

最終的に、私は通常、それぞれの特定のクエリに対してどちらがうまく機能するかを使います。

'' '' '

更新日:タイトルを修正しました。残りは無視してください。

さて、あなたのタイトルについて:LINQに関して、IEnumerableとIQueryableは非常に似ています。 どちらもほとんど同じ拡張メソッド(Select、Where、Countなど)を持ちますが、主な(唯一?)違いは、IEnumerableがパラメーターとして `+ Func `を取り、IQueryableがパラメーターとして ` Expression> +`を取るこ​​とです。 あなたは両方とも同じように表現しますが(通常はランバ表現)、内部的には完全に異なります。

IEnumerableはLINQ to Objectsへの入り口です。 LINQ to Objects拡張メソッドは、任意のIEnumerable(配列、リスト、 `+ foreach `で反復できるもの)で呼び出すことができ、 ` Func +`はコンパイル時にILに変換され、実行時に通常のメソッドコードのように実行されます。 他のLINQプロバイダの中にはIEnumerableを使用しているため、実際には裏でオブジェクトに対してLINQを使用しているものもあります(LINQ to XML、LINQ to DataSet)。

IQueryableは、LINQ to SQL、LINQ to Entities、およびコードを直接実行する代わりにクエリを調べて変換する必要がある他のLINQプロバイダによって使用されます。 IQueryableクエリとその「+ Expression> +」は、コンパイル時にILにコンパイルされません。 代わりに_expression tree_が作成され実行時に調べることができます。 これにより、ステートメントを他のクエリ言語(T-SQLなど)に翻訳することができます。 式ツリーは実行時にFuncにコンパイルし、必要に応じて実行することができます。

違いを説明する例はhttps://stackoverflow.com/questions/695678/performing-part-of-a-iqueryable-query-and-deferring-the-rest-to-linq-for-objects/にあります。 696014#696014 [この質問] OPがSQL ServerでLINQ to SQLクエリの一部を実行し、オブジェクトをマネージコードにし、残りのクエリをLINQ to Objectsで実行したい場合。 これを達成するために彼がしなければならないすべては、彼がスイッチが起こりたいところでIEnumerableにIQueryableをキャストすることです。


3


LINQは技術の流行語です。

IQueryableはLINQによって使用される.NETインターフェイスです。

スタイル以外は違いはありません。 どちらでも好きなスタイルを使ってください。

私は(ここに示されているような)長い文のための最初のスタイルと非常に短い文のための第二を好む。


2


最初の例のwhere節は、実際には2番目のメソッドのWhere節に対する単なる構文上の糖です。 実際、LinqやIQueryableとは関係のない独自のクラスを書くことができ、Whereメソッドを使うだけで、その構文糖を使うことができます。 例えば:

パブリッククラスMyClass {

public MyClassここで、(Func述語){return new MyClass {StringProp = "Hello World"}; }

public MyClass Select(関数述語){return new MyClass();} }


パブリック文字列StringProp {get;セット; }}

これは明らかに愚かな例ですが、stringpropをHello Worldに設定した新しいMyClassを返すWhereメソッドがあります。 実証するために:

MyClass a = new MyClass(); var q = from p a from p.StringProp == "foo" //ここでは、述語select pを実際にチェックしていないので、ここで指定した内容は関係ありません。 Console.WriteLine(q.StringProp);

これにより、「Hello World」と書き出されます。 繰り返しますが、この例は明らかに無意味ですが、「where」構文はコード内でFuncを取るWhereメソッドを探すだけであるという点を証明しています。


2


クエリ式と拡張メソッドはまったく同じことをする2つの方法です。 クエリ式は、コンパイル時に拡張メソッドに変換されます。これらは、SQLに慣れている人にとっては単なる構文上の糖です。

あなたがこれを書くとき:

var surveyNames = dbのsの中から選択s.Name;

コンパイラはこれを次のように変換します。

IQueryable surveryNames = db.Surveys.Select(s => s.Name);

実際、クエリ式はマーケティング上の理由から作成されたものだと思います。LINQが開発されたときに目を引くものとして機能するSQLのような言語構成要素であり、実際の用途はあまりありません。 C#とSQLが混在するのではなく、より統一されたコーディングスタイルになるため、ほとんどの人が拡張メソッドを直接使用するだけであることがわかりました。


1


  1. /あなたの質問タイトルはあなたが尋ねたものと一致しません。 2. /あなたの質問の題名はあまり意味がありません。 LinqはLanguage Integrated Queryの略で、一連のテクノロジとプラクティスの総称であり、IQueryableはLinqを容易にするために一般的に使用されるインタフェースです。 それは明らかに結果セットの進行を示しているように、私の個人的な好みは第2バージョンです。


1


あなたの* Sample1 はLinqのトップレベルの表現です、もっと読みやすく、そしてコンパイルしている間、それは式ツリー、すなわちあなたの Sample2 *に変換されます。

var x = from s db.Surveys sq = s.IDのsq.Survey_ID join q = sq.Question_ID = q.ID join qg in db.Question_Groups on q.ID Question_IDここでs.Type_ID.Equals(typeID)

あなたは書かれたクエリの式を取得するためのコードの下に試すことができます

var exp = x.Expression;

クエリがそれほど複雑でない場合は式が使用されます。


0


私はあなたの質問は「LINQに関してIEnumerableとIQueryableの違いは何ですか」というように表現したほうが良いと思います。

LINQクエリはデフォルトでIQueryableを返します。 IQueryableを使用すると、クエリを実行する前に、クエリに他のフィルタや「句」を追加できます。

LINQクエリ(最初の例)とメソッドチェーンを使用したLINQ(2番目の例)では、構文が異なり、同じ結果が得られます。

LINQクエリをLINQメソッドチェーンとして作成することも、その逆も可能です。 それは本当にあなたの好みによります。

@Lucas:違いは、IEnumerableがインメモリクエリを実行し、IQueryableがメモリ不足を実行することです。 つまり、「+ foreach 」イテレータに入ったらIEnumerableを使用し、拡張メソッドまたはLINQ「 from o in object +」シナタックスを使用してクエリを作成するときに、IQueryableを作成します。 列挙子に触れるとすぐにIQueryableが実行されます。


0


言及する価値があるもう1つの点は、Linq拡張メソッドはC#言語に準拠しているのに対し、クエリー理解のものはコンパイラに組み込まれているように前処理されているということです。 つまり、.Select(x ⇒の定義に移動できますが、 `+ from …​ どこで… 選択+ `