2016-10-25 10 views
1

が含まれていないテーブルを結合:は、私は次のデータベースを持っている何の関係

enter image description here

  1. 表メッセージ:

    • メッセージを格納するための責任は、異なる電子メールアドレスを行い送りました。
  2. 表の電子メール:

    • のメールアドレス(プライマリキー=メール) (toEmailは、テーブルの電子メールと関係を持っている)(Sotres [email protected]、foo2は@ gmailのを格納するための唯一の責任を負います。 COMなど)
  3. 表コンタクト:私たちを保存するために使用される

    • あなたの連絡先。連絡先が複数の電子メールアドレスを持っているかもしれないので(店舗はマーク、ジョン、トム、等...)
  4. 表のContactEmails

    • は、このテーブルが必要です。 私は特定の日付の間に送信されたすべてのメッセージを選択しますクエリを作成したい:とにかく、ここで(店舗テーブルの電子メールで見つかったIDS)

質問です。 問い合わせ名に連絡先の名前が含まれている場合は、とします。私は、次のクエリをcratedしているが、それは遅くすることです:

Func<string, Contact> tryGetContact = (email)=>{ 
    var contactEmail = db.ContactEmails.FirstOrDefault(x=>x.IdEmail==email); 
    if(contactEmail==null) 
     return null; 
    return contactEmail.Contact; // navigational property created by entity framework. 
}; 

var query = from msg in db.Messages 
      join email in db.Emails on msg.ToEmail equals email.Email 
      where msg.Date < "some date" && msg.Date > "some other date" 
      select new 
      { 
       MessageSubject = msg.Subject, 
       ToEmail = email.Email, 
       Contact = tryGetContact(email.Email) // this slows down the query! 
      }; 

私のクエリは速く、私は辞書内のすべての連絡先を保存し、2つのクエリにこのクエリを分離する必要があります実行させるためには?

すべての連絡先を辞書に保存すると、はるかに効率的になります。しかし、私がそれらのほとんどを必要としないデータベースからすべての連絡先を取得することは、私がリソースを無駄にしていると感じさせる。

+0

MS SQLサーバーのようなサーバーベースのデータベースを使用していますか?そのような場合は、ストアドプロシージャまたはクエリで直接クエリを実行する方が早くなります。 –

+0

あなたのデータベースに 'ContactEmails.IdEmail'がインデックスされていますか?要求をどのように書くかにかかわらず、少なくともそのインデックスを定義していないと、良いパフォーマンスを得ることはできません。 – sstan

+0

はい私は1つのMS SQLサーバーデータベースしか持っていません。問題は、連絡先に属していないメールアドレスにメッセージを送信することがあることです。だから私は自分のデータベースにその関係がないのです。 –

答えて

3

Linqクエリによって生成された実際のSQLを見ることができれば、クエリが遅くなっているかどうかを判断する方が簡単です。しかし、私はあなたのtryGetContact Funcと関係があるかもしれないと思います。これは、クエリの主要部分と同じコンテキストを共有していません。

私は右だのであれば、あなたは新しい完全なクエリがあるため、この行で実行されますtryGetContact(email.Email)を呼び出すたび:その場合db.ContactEmails

var contactEmail = db.ContactEmails.FirstOrDefault(x=>x.IdEmail==email); 

はそうSQLクエリで結合の一部ではありません毎回再実行されます。

だから、joinを追加して、ContactEmailsをLinq(およびその後のSQL)クエリに含めることです。これは、そのように見えるはずです。

var query = from msg in db.Messages 
      join email in db.Emails on msg.ToEmail equals email.Email 
      join contactEmail in db.ContactEmails on contactEmail.IdEmail equals email.Email 
      where msg.Date < "some date" && msg.Date > "some other date" 
      select new 
      { 
       MessageSubject = msg.Subject, 
       ToEmail = email.Email, 
       Contact = (contactEmail==null) ? contactEmail.Contact : null, 
      }; 

これはすべてのあなたのtryGetContactのコールに対して一度だけdb.ContactEmailsを実行し、(パフォーマンスの向上にはHashSetの)コレクションに結果を格納することがあります動作しない場合。

+0

何か不足していますか?しかし、あなたは 'ContactEmails'の内部結合を実行していないのですか?電子メールの既存の連絡先がない場合、結果を効果的にフィルタリングしますか? – sstan

+0

はい、それは減速しています。連絡先をハッシュセットに保存してから、すべてをメモリに保存する必要があります。助けてくれてありがとう! –

+0

あなたは正しいsstanですが、これは外部結合では避けてください。 Tono Namを助けてくれてうれしい! – Vyrira

関連する問題