2009-08-10 8 views
5

これらの2つのステートメントの違いは何ですか?LINQ: 'Select c'と 'Select new(c ...')の違い

 var result = from c in context.CustomerEntities 
join p in context.ProjectEntities on c.Pk equals p.CustomerPk 
where p.Entered > DateTime.Now.AddDays(-15) 
select c; 

および

 var result = from c in context.CustomerEntities 
join p in context.ProjectEntities on c.Pk equals p.CustomerPk 
where p.Entered > DateTime.Now.AddDays(-15) 
select new (c.Company, c.Entered, c.pk); 

これらのステートメントにはパフォーマンス関連の問題はありますか。 (簡単にするために、cはこれらの3色のみを含んでいます。)

ありがとう。

答えて

10

これら二つの文

最初の戻り完全/元のソースオブジェクトのフィルタ配列の違いは何です。 2番目のフィルタは依然としてフィルタを行いますが、というちょうどという3つのプロパティを持つ匿名型のシーケンスを返します。

パフォーマンスは、バックエンドに依存し、これらのステートメントのいずれかのパフォーマンス関連の問題があります。これがLINQ-to-Objectsの場合、new {...}を使用すると、レコードごとに余分なオブジェクト(匿名タイプ)が作成されるため、オーバーヘッドが非常に小さくなる可能性があります。ただし、LINQ-to-SQLなど(データベースのバックエンド)の場合は、というメリットになる可能性があります。クエリビルダーは、必要な列をチェックし、anon型で3つだけを取得します。あなたのデータにBLOB(または単に長いvarchar)が必要でない場合は、巨大なというメリットがあります。

その他の注意事項:あなたは、この目的のために、独自のDTOの型を宣言する必要があるかもしれませんので、あなたは、メソッドのシグネチャに匿名型を含めることはできません。

return new CustomerDto { Company = c.Company, Entered = c.Entered, PK = c.pk}; 
... 
public class CustomerDto { ... } 
+1

+1一般的な答えは、彼の状況では、とにかくすべての列を返しています。 – cjk

+0

はいckは正しいです。私はすべての列を返しています。 – Waheed

1

の疑いで、プロファイル場合。

しかし、はい、私はパフォーマンスのオーバーヘッドがあると思います。 select cの場合、コレクションには元のアイテムへの参照が含まれます。 select new { ... }を行う場合、C#はあなたのために匿名型を作成し、その型の新しいインスタンスを作成し、それらをデータで埋めています。間違いなく私には遅く聞こえる。

+0

+1のプロファイリングを推奨します。 – Marcel

2

主な違いは、最初の例では既存のインスタンスへの参照が返され、2番目の例では匿名型の新しいインスタンスが作成される点です。可能性のあるパフォーマンスの問題よりもこの問題に関心があります。

2

私はいくつかのテストを実行しました(使用しましたストップウォッチ)。 Linq-to-SQL(SQL Serverに対して)、Linq-to-Entities(MySQLに対して)、Linq-to-Objects(リストに対して)では、匿名の型は高速化されませんでした。実際には、選択する列の数に応じて通常は遅くなりました。

私の結果の1つ: Linq-to-Entitiesを使用して400行ずつ読み込まれた5列の表に対して、各問合せを5000回実行しました。

匿名オブジェクト(1列を選択):17314ms

匿名オブジェクト(5列を選択):

ソースオブジェクト19193ms:とにかく

、それをテストするためにされて見つけるための最善の方法を16055msあなた自身(良いポストを書く時間がかかります)。

関連する問題