2009-07-02 1 views
0

メッセージの受信者の1人がユーザーと一致するデータベースからメッセージのリストを取得しようとしています。一つだけの受信者があった場合、通常、次の1つのキーがArrayOfIntで、もう1つがintのときにLINQ結合する方法

var res = db.messages.Where(m => m.id == message_id) 
       .Join(db.persons, m => m.recipients, p => p.id, (m, p) => new {m, p}) 
       .Select(x => new Message(){ msg = x.m, person = x.p}) 

しかし、どのような受信者場合は、整数とidのカンマ区切りの文字列であることは整数である?のようなものを持っているでしょうか

+0

できません。 http://social.msdn.microsoft.com/Forums/en-US/linqtosql/thread/d2791ad4-3897-4fc0-80e9-72ebc4822898 – sean

+0

以下は有用な情報でもあります。http://tomasp.net /blog/linq-expand.aspx – sean

答えて

0

オプション1 - 使用は含まれています:

var res = from m in db.messages 
      where m.id == message_id 
      from p in db.persons 
      where m.recipients.Split(",").Select(i => Int32.Parse(i)) 
       .Contains(p.id) 
      select new Message() { 
       msg = m, 
       person = p 
      }; 

アイデア:

  1. あなたの元のクエリのようなメッセージ
  2. は、受信者リスト
  3. に含まれるすべての者が続行をゲット元のクエリで

オプション2 - 参加LINQを使用して(それが必要以上に多分もっと複雑):

var res = from m in db.messages 
      where m.id == message_id 
      from r in m.recipients.Split(",") 
      select new { 
       Message = m, 
       Recipient = Int32.Parse(r) 
      } into rec 
      join p in db.persons on rec equals p.id 
      select new Message() { 
       msg = m, 
       person = p 
      }; 

アイデア:

  1. があなたの元のクエリ
  2. スプリトのようなメッセージを受信しましょう! Int32のリストに文字列
  3. このリストに登録するdb.persons
  4. riginalクエリ

高速ですこれらのどの、あなたがチェックする必要がありますわかりません。

私はまた、外部キーリファレンスとしてカンマ区切り文字列を使用することを恥ずかしく思っています。つまり、ここで問題が発生しているためです。彼らは見ることが醜く、操作する真の痛みです。代わりに、スキーマを制御できる場合は、MessageIdPersonIdの1対多の関係表を検討してください。もちろん、あなたがコントロールを持っていなければ、あなたは立ち往生しています。

免責事項:これらはテストされていないため、コードを動作させるためには微調整が必​​要な場合があります。しかしアルゴリズムは大丈夫です。

+0

私は最初にクエリを単純化しましたが、今ははっきりしているはずです。 – sean

+0

ラムダ構文であればいいですが、試してみましょう。そして、おそらくパースは必要ありません。人のIDの.ToString()で十分でしょうか? – sean

+0

Okあなたの選択に合うように最後をきれいにしました。 –

1

受信者を最初に要素のリストに変換する必要があります。私は受信者が人テーブルからのidsのリストであると仮定しています。そのようなあなたの質問からあなたはそれに選択を行うには、人のIDに渡す必要がありますか? LINQでこれを行うことは.Splitのようなものなどのパフォーマンスペナルティを受けるために起こっていることを

var messages=db.messages.Select(
     m => m.id == message_id && 
     (m.recipients.Split(","). 
      Any(recipient => reipient == person_id) 
     ) 

var person = db.Persons.Select(p => p.id == person_id) 

ノートは、C#で、のIQueryable上では動作しません。そのため、DBは、テーブルのサイズに応じて、このクエリを実行するために多くのデータを送信する必要があります。これをトークン化したときにデータベースのビューを持っている場合や、メッセージの受信者がメッセージIDとともにリストされているDBに新しいテーブルを作成できる場合は、これをもっと簡単に行うことができますその過程であなたのDBを正規化することに言及してください)。

+0

私はそれを試してみましょうが、どうすればpにアクセスできますか?はい、新しいテーブルを作成する方が簡単ですが、既存の構造との結合が可能かどうかを調べたいだけでした。 結果がキャッシュされると、パフォーマンスの低下は軽減されますか? – sean

+0

私はまた、クエリ構文を使用して、.Contains()を使用すると、トリックを行うだけかもしれないと思っていますが、ラムダではどうやってやりますか – sean

+0

あなたのクエリは特定の人物IDのメッセージを取得していましたか?その質問はこれでした。あなたは、特定のメッセージが宛てられた人のリストの後にいますか?それは別のクエリです... – Spence

関連する問題