Подтвердить что ты не робот

Linq to Entities от многих до многих запросов

Я в затруднении со следующим запросом, который является арахисами в обычном T-SQL.

У нас есть три физических таблицы:

  • Полоса (PK = BandId)
  • MusicStyle (PK = MuicStyleId)
  • BandMusicStyle (PK = BandId + MusicStyleId, FK = BandId, MusicStyleId)

Теперь то, что я пытаюсь сделать, это получить список MusicStyles, которые связаны с Band, который содержит определенную строку поиска в названии. Имя полосы также должно быть в результатах.

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%'

Как я могу написать это в Linq To Entities?

PS: StackOverflow не разрешает поиск по строке "многие-многие" по какой-то причине bizar...

4b9b3361

Ответ 1

Это оказалось намного проще, чем казалось. Я решил проблему, используя следующий blogpost: 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

Это гарантирует, что вы будете фильтровать только группы, имеющие музыкальный стиль.

Спасибо за ваши ответы, но ни одна из них не решила мою проблему.

Ответ 2

В 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};

Если вы посмотрите на сгенерированные классы сущностей, BandMusicStyle не должен появляться, поскольку LINQ to Entities считают, что Band и MusicStyle много для многих, и эта таблица не нужна.

Посмотрите, работает ли он?

Ответ 3

Вы можете сделать выше, но это приведет к возврату всех ваших результатов, как только вы начнете их перебирать, и фильтрация выполняется в памяти, а не на db.

Я думаю, что вы ищете только несколько подключений?

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 };

или что-то в этом роде

Ответ 4

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.
}