2012-01-31 16 views
7
var queueitem = context.CrawlerQueues. 
       Select(cq => new{cq.Guid,cq.Result}). 
       SingleOrDefault(cq => cq.Guid == guid); 

これは悪い考えではありません。最初はすべてのデータベース行を選択してから、それを見つけるかスマートにして、その中で使用されているコンテキストを参照して1つの行だけをフェッチします。Linqはselect()です。SingleorDefault()は悪い考えですか?

これを行う理由は、私はGuidとResult coloumsだけを返したいと思っています。

return Newtonsoft.Json.JsonConvert.SerializeObject(queueitem, Formatting.Indented); 

ネットワークフローやデータベースへの要求を監視しなくても、これに対する回答をどのように見つけることができますか?

答えて

13

は、「それは最初にすべてのデータベースの行を選択し、1でしょう」

技術を、いや、.SingleOrDefault続く.Selectの組み合わせは、それを行うことはありません。 Select()はクエリのパラメータを設定しますが、実際にはデータをフェッチしません。 LINQの遅延実行では、実際にデータ結果を生成する必要が生じるまで、行がフェッチされません。複数のクエリを一緒に構成する(.Select(...)、Select(..)など)、First()や.ToList()などのデータを返す操作を実行するまでは、実際には何も行をフェッチしません。

ただし、Single()を使用すると、一致する行が唯一の一致する行であることを証明するためにデータセット全体をスキャンすることがあります。

考えてみましょう:1行が一致するデータセット内の行だけです。次の行を見つけようとする必要があります。実際にデータセット内の何百万ものものと一致する行が1つしかない場合、現在の一致が唯一の一致であることを証明するために、Single()はそれらの何百万もの行すべてを実行する必要があります。

データセットがSQLで、クエリの最適化を可能にする方法でデータのインデックスが作成されている場合、Single()はそれほど悪くない可能性があります。しかし、あなたのSQLデータがこのクエリに役立つ方法で索引付けされていない場合、Single()はSQLサーバーのために多くの作業を作成する可能性があります。

プログラムロジックが、返された行がデータセット全体の中の唯一の行であることを実際に知る必要がある場合は、Single()が適切です。ただし、一意性を保証する他の方法もあります。 LINQ条件に一致するデータにプライマリキーを設定できる場合、最初に一致する行が1つだけ存在するかデータベースに追加されるため、実際にはSingle()は必要ありません。 (主役のインデックスを使ってクエリを最適化できるため、皮肉なことに、この場合でもSingle()のパフォーマンスは非常に速くなります)

条件に一致する最初の行だけが必要な場合は、First )をSingle()の代わりに使用します。 First()は最初の一致が見つかるまで、データの行をスキャンするだけです。 Single()のように最初の一致が唯一の一致であることを証明するために行をスキャンし続ける必要はありません。

+0

ありがとうございます。私はfirstordefaultを使用していますが、質問をするとどうにか忘れてしまいます。 –

+0

私はFirstOrDefault()も提案しようとしていました。 –

1

実際に実行される実際のクエリは実際にはLinqプロバイダに依存しますが、Linqプロバイダはクエリを実行する前にコンテキスト(SingleOrDefault)を知るように最後まで評価しません。良いものは必ずしも必要ではありません。

良いLinqの実装は実際に2行をフェッチします。なぜなら、SingleOrDefaultは3つのケースを処理するからです。

  • なし行が返されていない - >戻るデフォルト行が返さ
  • 1 - >スロー例外(シーケンスが複数の要素を含んでいる)
2

- >は、

  • 複数の行が返され、その行を返しますSingleOrDefault - シーケンスの唯一の要素を返します。シーケンスが空の場合はデフォルト値を返します。 のシーケンスに複数の要素がある場合、このメソッドは例外をスローします。

    FirstOrDefault - シーケンスの最初の要素を返します。シーケンスに要素がない場合は、デフォルト値を返します。

    意味的には、あなたの質問には複数の行が返されたことが記載されているので、FirstorDefaultが必要です。

  • +1

    あなたは正しいですか?しかし、それは質問された質問ではありませんでした。 –

    3

    「評価」ステートメントの実行後(このクエリのSingleOrDefault())まではクエリの実行が行われないため、フィルタリング前にデータベース全体が返されないことは間違いありません。

    あなたは

    context.CrawlerQueues.ToList().Select(cq => new{cq.Guid,cq.Result}).SingleOrDefault(cq => cq.Guid == guid)を持っていた場合。

    この場合、フィルタリングする前にToList()と評価されますが、そのままのクエリは問題ありません。

    評価パスまたは生成されたSQLがLINQステートメントから不明な場合は、LINQPadがLinq、Linq2Sql、EFで作業するのに非常に優れたツールです。

    関連する問題