4

(エンティティ フレームワークを使用)

私が書くとき:

IEnumerable<string> q = customers /*EF entity*/
.Select (c => c.Name.ToUpper())
.OrderBy (n => n)

C# コンパイラは式ツリーを出力する方法を認識しており、それによって SQL が実行されます。

SELECT UPPER (Name) FROM Customer ORDER BY UPPER (Name)

order by節があることにも注意してください

しかし

私はこのリンクを見ました :

彼が書きました :

IEnumerable<employee> emp = 
         dc.Employees.Where(x => x.Desc.StartsWith("soft"));
emp = emp.Take(1);

彼が見た最後のクエリを調査した後:

SELECT [t0].[Id], [t0].[Name], [t0].[Address], [t0].[Desc] AS [Desc]
FROM [dbo].[Employee] AS [t0]
WHERE [t0].[Desc] LIKE @p0

条項がないことに注意してください top

何故ですか ?

Take(x)クエリに追加しないでください。

次のように書きます:

IEnumerable<employee> emp = 
         (dc.Employees.Where(x => x.Desc.StartsWith("soft"))).Take(1);

SQL に送信されるクエリに TOP 句を追加しますか?

ここで何が起こっているのですか?

take(私はそれが遅延実行ではないことをすでに知っています)

4

2 に答える 2

9

Take(1)最初の式に追加すると、 onIQueryable<T>になり、SQL に追加されます。しかし、 に変換IQueryable<T>したためIEnumerable<T>Take(1)はメモリ内で行われます:IEnumerable<T>同じ名前のTake()拡張メソッドがあり、コンパイラが知る限り、empIEnumerable<T>ではなくIQueryable<T>、メモリ内バージョンが呼び出されます。

于 2012-06-22T13:36:30.350 に答える
5

などの拡張メソッドTake()は静的メソッドであり、コンパイル時に解決されます。

emp のコンパイル時の型はIEnumerable<employee>(明示的に 1 として宣言されているため) であるため、コンパイラはEnumerable.Takeの代わりにQueryable.Takeを選択します。これはクエリ変換を実行しません。

あなたが怠け者varで、型名の代わりに使用した場合:

var emp = dc.Employees.Where(x => x.Desc.StartsWith("soft"));
emp = emp.Take(1);

コンパイラがIQueryable<employee>emp を選択したため(初期化する式がその型であるため)、したがってQueryable.Take2番目の呼び出しで機能したはずです。

于 2012-06-22T13:45:09.240 に答える