2016-11-30 8 views
1

私はTelerik Open/Data Access ORMをORACLEに対して使用しています。LINQから生成されたSQLに一貫性がありません

これらの2つのステートメントの結果、SQLコマンドが異なるのはなぜですか?以下のSQLで

ステートメント#1

IQueryable<WITransmits> query = from wiTransmits in uow.DbContext.StatusMessages 
      select wiTransmits; 

query = query.Where(e=>e.MessageID == id); 

結果、以下のSQLで

SELECT 
    a."MESSAGE_ID" COL1, 
    -- additional fields 
FROM "XFE_REP"."WI_TRANSMITS" a 
WHERE 
    a."MESSAGE_ID" = :p0 

書#2

IQueryable<WITransmits> query = from wiTransmits in uow.DbContext.StatusMessages 
      select new WITransmits 
      { 
       MessageID = wiTranmits.MessageID, 
       Name = wiTransmits.Name 
      }; 

query = query.Where(e=>e.MessageID == id); 

結果

SELECT 
    a."MESSAGE_ID" COL1, 
    -- additional fields 
FROM "XFE_REP"."WI_TRANSMITS" a 

2番目のステートメント#2で生成されたクエリは、明らかに、テーブル内のすべてのレコードを返します。何百万という記録がこれを禁じられています。

+0

投影がORMによって「IEnumerable」として返されるように見えます。最初のステートメントの後の両方のケースで 'query'の型は何ですか? –

+0

彼らは両方ともIQueryableです(更新されたオリジナルのポスト) –

+0

具体的なタイプは? –

答えて

0

最初のクエリは定義された完全オブジェクトを返します。したがって、実際に実行される前に追加の制限(Whereなど)を追加できます。したがって、あなたが示したようにクエリを組み合わせることができます。

2番目のオブジェクトは新しいオブジェクトを返します。新しいオブジェクトは、どのような型でも何でも構いません。したがって、クエリはデータベースに "すべて返す"として送信され、オブジェクトが作成された後にWhere句に一致するもの以外のすべてが破棄されます。

タイプは、それらの両方で同じであったにもかかわらず、このような状況を考える:

var query = from wiTransmits in uow.DbContext.StatusMessages 
    select new WITransmits 
    { 
     MessageID = wiTranmits.MessageID * 4 - 2, 
     Name = wiTransmits.Name 
    }; 

あなたが今Whereクエリを組み合わせることだろうか?確かに、新しいオブジェクト作成内のコードを調べて外に移動しようとしますが、なのでになる可能性はありません。検査があるルックアップ機能の場合はどうなりますか?確定的でない場合はどうなりますか?

したがって、データベースオブジェクトに基づいて新しいオブジェクトを作成すると、オブジェクトが取得され、さらにメモリ内でクエリが実行される境界が存在します。

+0

Entity FrameworkのようなORMでは、 'wiTranmits.MessageID * 4-2 'を含む式全体がSQLに変換されるため、' MessageID'によるソート/フィルタリングもクエリに表示されます。私はTelerikがここでは別の戦略を持っていると思う。 –

+0

おそらく、MessageID = LocalFunction(wiTransmits.MessageID)、 – David

1

Telerik Data Accessは、各クエリをデータベース側とクライアント側(または必要に応じてメモリ内のLINQ)に分割しようとします。
select newで投影することは、投影後にLINQ式ツリーのすべてをクライアント側に移動させるトリガーになります。
2番目のケースでは、メモリ内でフィルタリングが適用され、多くの不要なデータが既に転送されているため、非効率なLINQクエリが発生します。
ケース2で行われた方法でLINQ式を作成する場合は、最後にSelect句を追加するか、結果をIEnumerable<T>に明示的に変換して、それ以降の処理はメモリ内で行われることがわかります。

関連する問題