46

いくつかの EF データ リポジトリを実装しており、以下を含むいくつかのクエリがあります。TOP 1

.Take(1)
使用を提案する多くの投稿を読みました.First()

これらは両方ともオブジェクトの割り当てに対して同じ結果を生成することを理解していますが、実際には両方とも同じクエリに解決されますか? DB にクエリを実行すると、実際にTOP 1は両方のリクエストに対応しますか? それとも、クエリを列挙型に完全に実行してから、コレクションの最初のエントリを取得するだけですか?

さらに、使用した場合.FirstOrDefault()、なぜ異なる動作を期待する必要があるのでしょうか? IEnumerable を使用する場合.First()、空のコレクションを呼び出すとスローされることはわかっていますが、これ実際にクエリを変更してインクルードするだけである場合、と....TOP 1の間に機能的な違いはまったくないと予想する必要があります。.First().FirstOrDefault()

または、クエリを実行するためのこれらの列挙可能な拡張よりも優れた方法はありますTOP 1か?

4

5 に答える 5

82

LINQPadから:

C# :

age_Centers.Select(c => c.Id).First();
age_Centers.Select(c => c.Id).FirstOrDefault();
age_Centers.Select(c => c.Id).Take(1).Dump();

SQL :

SELECT TOP (1) [t0].[Id]
FROM [age_Centers] AS [t0]
GO

SELECT TOP (1) [t0].[Id]
FROM [age_Centers] AS [t0]
GO

SELECT TOP (1) [t0].[Id]
FROM [age_Centers] AS [t0]

* をTake(1)列挙して返すことに注意してくださいIQueryable

于 2012-05-04T20:19:40.393 に答える
5

DataContext Logプロパティを Console.Out または TextFile にリダイレクトし、各オプションが生成するクエリを確認します。

于 2012-05-04T20:07:42.910 に答える
2

仕組み.First():

コレクションが IList 型の場合、最初の要素は、コレクションの実装によって異なるインデックス位置によってアクセスされます。それ以外の場合、反復子は最初の要素を返します。

そして.Take(int count)常に繰り返します。

ゲインがある場合は、コレクションが実装さIListれ、インデックスによって最初の要素にアクセスする速度がイテレータを返す速度よりも速い場合に発生します。私はそれが重要になるとは思わない。;)

ソース:

http://www.hookedonlinq.com/FirstOperator.ashx

http://www.hookedonlinq.com/TakeOperator.ashx

于 2012-05-04T20:16:07.180 に答える
1
**First()** operates on a collection of any number of objects and returns the first object.        **Take(1)** operates on a collection of any number of objects and returns a collection containing the first object.

また、Single を使用することもできます 。Single()は、1 つのオブジェクトのコレクションに対して動作し、単にオブジェクトを返します。

于 2014-11-05T14:09:54.493 に答える
1

最初に Take 1 をクエリしますので、クエリに違いはありません。Take は IEnumerable を返すため、FirstOrDefault の呼び出しは 1 ステップのステートメントになります。とにかく First を呼び出す必要があります。

First は例外をスローするため、常に FirstOrDefault が優先されます。

もちろん、EF クエリ コンバーターを作成した人は、結果セット全体を実行して最初の項目を返す代わりに、Take 1 を呼び出すほど賢いです。

これは、SQL プロファイラーを使用して確認できます。

于 2012-05-04T20:21:06.503 に答える