web-dev-qa-db-ja.com

Linq toEntities多対多の選択クエリ

プレーンなT-SQLのピーナッツである次のクエリで途方に暮れています。

3つの物理テーブルがあります。

  • バンド(PK = BandId)
  • MusicStyle(PK = MuicStyleId)
  • BandMusicStyle(PK = BandId + MusicStyleId、FK = BandId、MusicStyleId)

今私がやろうとしているのは、名前に特定の検索文字列を含むバンドにリンクされているMusicStylesのリストを取得することです。バンド名も結果に含まれている必要があります。

T-SQLは次のようになります。

SELECT b.Name, m.ID, m.Name, m.Description
FROM Band b 
INNER JOIN BandMusicStyle bm on b.BandId = bm.BandId
INNER JOIN MusicStyle m on bm.MusicStyleId = m.MusicStyleId
WHERE b.Name like '%@searchstring%'

これをLinqTo Entitiesでどのように記述しますか?

PS:StackOverflowは、奇妙な理由で「多対多」という文字列の検索を許可していません...

18
Peter

これは、見た目よりもはるかに単純であることがわかりました。次のブログ投稿を使用して問題を解決しました: http://weblogs.asp.net/salimfayad/archive/2008/07/09/linq-to-entities-join-queries.aspx

このソリューションの鍵は、ミュージックスタイルコレクションのバンドのサブセットにバンド名のフィルターを適用することです。

var result=(from m in _entities.MusicStyle 
            from b in m.Band
            where b.Name.Contains(search)
            select new {
                BandName = b.Name,
                m.ID,
                m.Name,
                m.Description
            });

行に注意してください

from b IN m.Band

これにより、音楽スタイルのあるバンドのみをフィルタリングすることができます。

あなたの答えに感謝します、しかしそれらのどれも実際に私の問題を解決しませんでした。

27
Peter

Linqでは、実際には何も記述する必要はありません。SQLデータベースのダイアグラムでリレーションを定義し、ユーティリティを使用して生成すると、オブジェクト階層が自動的に構築されます。つまり、次の場合です。

var bands = from ms in db.MusicStyle
            let b = ms.Bands
            where b.Name.Contains(SEARCHSTRING)
            select new {
                b.Name, ms.Name, 
                ms.ID, ms.Description};

生成されたエンティティのクラスを調べる場合、LINQ to Entitiesは、BandとMusicStyleが多対多であり、そのテーブルは不要であると見なしているため、BandMusicStyleは表示されないはずです。

それが機能するかどうかを確認しますか?

4
xandy

上記を行うこともできますが、反復を開始し、フィルタリングがデータベースではなくメモリ内で行われると、すべての結果が返されます。

あなたが探しているのはほんの数人の参加だと思いますか?

var q = from b in db.Bands
join bm in db.BandMusicStyle on on b.BandId equals bm.BandId
join ms in db.MusicStyle on bm.MusicStyleId equals m.MusicStyleId
where b.Name.Contains(searchString)
select new { b.Name, ms.ID, ms.Name, ms.Description };

またはとにかくこの効果に何か

1
Ciaran O'Neill
from ms in Context.MusicStyles
where ms.Bands.Any(b => b.Name.Contains(search))
select ms;

これは、あなたの質問が求めるスタイルを返すだけです。一方、サンプルSQLは、スタイルとバンドを返します。そのために、私はします:

from b in Context.Bands
where b.Name.Contains(search)
group b by band.MusicStyle into g
select new {
    Style = g.Key,
    Bands = g
}

from b in Context.Bands
where b.Name.Contains(search)
select new {
    BandName = b.Name,
    MusicStyleId = b.MusicStyle.Id,
    MusicStyleName = b.MusicStyle.Name,
    // etc.
}
0
Craig Stuntz