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...
Ответы
Ответ 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.
}