2017-04-24 3 views
5

私はEF 6で困惑しています....私はパフォーマンスの面で非常にひどく動作するWebアプリケーションを持っています。分析中、EF6エンティティ上でコレクションが空であるかどうかをチェックする私の方法である犯人の1つが見つかりました。EF6 - 私が期待したことをしない.Any()

基本的に、私が持っている:私のアプリで

public partial class BaseEntity 
{ 
    public int BaseEntityId { get; set; } 
    public string Name { get; set; } 

    // a few more properties, of no concern here.... 

    // a lazily loaded collection of subitems   
    public virtual ICollection<Subitem> Subitems { get; set; } 
} 

public partial class Subitem 
{ 
    public int SubitemId { get; set; } 
    public int BaseEntityId { get; set; } 
    public string Name { get; set; } 

    // a few more properties, of no concern here.... 
} 

を、私はBaseEntityの特定のインスタンスが「空」であるか否かをチェックする必要がある - 何のサブ項目を有していないと定義されています。だから私は、第二の部分クラスファイルにこの方法CheckIfEmptyを追加しました:今

public partial class BaseEntity 
{ 
    public bool IsEmpty 
    { 
     return !Subitems.Any(); 
    } 
}   

単一BaseEntityは、サブ項目の数百または数千を持つことができます - ので、私は、任意のサブ項目があったかどうかをチェックするために最も効率的な方法を使用していました。またはそれらの線に沿って何か - - ただの項目が存在していたかどうかをチェックする - マイ仮定がデータベースからまだロードされていないコレクションで.Any()を呼び出すと、基本的に

IF EXISTS(SELECT * FROM dbo.Subitems) ...... 

SQL呼び出しに変換というものでしたかない。私は具体的にはより.Count > 0を選択しました。なぜなら、カウントのチェックでコレクション全体が列挙される必要があることがわかっていて、アイテムが存在するかどうかを知りたいときには非常に非効率的です。

私は存在し、また私は彼らの細部に興味がありますどのように多くのを知っている必要はありません- 十分であろうis empty?質問には、単純なYESまたはNO。私の大きな驚き(およびbedazzlement)へ

、それはEF6がコレクション全体をロードSELECTステートメントに、この単純な.Any()コールをオン判明します! - か - - それは間違いなく私は......

駆け引きいたものではありませんので、未ロードのコレクションは、任意の値を持っている場合、単純にをチェックする簡単な方法があるなしデータベースから完全なコレクションをロードしますか?イーガーローディングアプローチを使用してDbSetを照会することにより

+0

context.Set<TEntity>().Any();

はに翻訳されこれは怠惰な読み込みが実装されている方法です。最初に 'Subitems'にアクセスすると、それがロードされます。私はレイジーローディングを使用しないことを試みますが、それは私のコードを複雑にします:私はできるだけ早くコンテキストを閉じ、 'db.Subitem.Any(si => si。BaseEntityId == .. ) ' – Kobi

+0

' SubItems'は 'ICollection'です。 'IQueryable'であれば期待通りに動くかもしれません(I'm確かではありません。レイジーローディングが' IQueryable'でも使えるかどうかはわかりません) –

+1

Eagerのロード方法を使用してDbSetをクエリすると、あなたが望むものを手に入れよう: context.Set ()。どれか(); MSDNの(ビットとして0)ELSE CAST(BIT AS 1)CAST THEN ( が[M]と[TEntity] FROM 1 選択) END – alessalessio

答えて

5

、あなたが望む結果を得る:Subitems`も `前に、すべての項目をロード`呼び出す

SELECT CASE WHEN EXISTS (SELECT 1 FROM [TEntity] AS [m]) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END 
+0

もう一度ありがとう - すばらしい答え。 context.Subitems.Any(si => si.BaseEntityId == 42);を使用するように少し修正しました。これはまたうまく動作します。素晴らしいアプローチ - ありがとう!それは助けてくれてうれしいです。 –

+0

乾杯 – alessalessio

関連する問題