2009-07-08 20 views
17

Brakuje mi następującej kwerendy, która jest orzeszkami ziemnymi w prostym T-SQL.Linq do Encji od wielu do wielu wybierz zapytanie

Mamy trzy tablice fizyczne:

  • Band (PK = BandId)
  • MUZYKI (PK = MuicStyleId)
  • BandMusicStyle (PK = BandId + MusicStyleId, FK = BandId, MusicStyleId)

Teraz próbuję uzyskać listę MusicStyles, które są powiązane z zespołem, który zawiera pewien łańcuch wyszukiwania w jego nazwie. Nazwa zespołu powinna być również w wyniku.

T-SQL byłoby coś takiego:

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

Jak piszę to w LINQ do podmiotów?

PS: StackOverflow nie pozwala na wyszukiwanie na strunie „wiele do wielu” dla niektórych bizar powodu ...

Odpowiedz

27

To okazało się być znacznie prostsze niż wydawało. Rozwiązałem problem za pomocą następującego wpisu na blogu: http://weblogs.asp.net/salimfayad/archive/2008/07/09/linq-to-entities-join-queries.aspx

Kluczem do tego rozwiązania jest zastosowanie filtru nazwy zespołu w podzbiorze pasm kolekcji musicstyle.

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

Zawiadomienie linia

from b IN m.Band 

To sprawia, że ​​na pewno są tylko filtrowanie na zespoły, które mają MUZYKI.

Dziękuję za odpowiedzi, ale żaden z nich nie rozwiązał mojego problemu.

+1

jeśli potrzebujesz połączenia z lewej strony zamiast połączenia wewnętrznego, możesz może zastąpić 'from b in m.Band' z' from b in m.Band.DefaultIfEmpty() '. –

+0

Prosty, ostry i użyteczny. Dzięki. – QMaster

+0

@Peter, jeśli używamy metody linq, jakiej metody powinienem użyć, aby opisać składnię 'from .... from ....? czy mógłbyś podać przykład w metodzie linq. dzięki – Willy

4

w LINQ, faktycznie nie trzeba nic pisać, jeśli zdefiniować relację diagram w bazie danych SQL i generowany przy użyciu narzędzia hierarchia obiektów jest budowana automatycznie. Oznacza to, że jeśli zrobić:

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

Jeśli spojrzeć na wygenerowanych klas podmiotów, BandMusicStyle nie powinien pojawić się jako LINQ do podmiotów uznają, że zespół i MUZYKI wiele do wielu, że tabela nie jest konieczne.

Sprawdź, czy to działa?

+0

Tabela BandMusicStyle nie pojawia się w moim modelu danych. Po prostu chcę mieć listę stylów muzycznych, które są powiązane z zespołem z wyszukiwarką w jej nazwie. W jaki sposób uzyskasz listę obiektów, które nie będą pasować do zapytania, używając nazw pasma, MusicStyleId, MusicStyleName i MusicStyleDescription? Nie chcę mieć do iteracji poprzez tę listę i ręcznie ją później ... – Peter

+0

Tabela BandMusicStyle NIE pojawi się w modelu encji. Celowo jest to wykonywane przez LINQ do Entities, bo uważa się, że stół pośredni to po prostu "wiele-wiele złączeń", więc nie będzie generowany, a nie jak Linq 2 SQl. Jeśli TYLKO potrzebujesz tych pól, możesz wybrać te w instrukcji select: wybierz nowy {b.Nazwa, b.MusicStyle.Name, b.MusicStyle.ID, b.MusicStyle.Description}; – xandy

+0

Tak, wiem, że się nie pojawił ... Problem z aktualnym zapytaniem polega na tym, że b.Musicstyle jest kolekcją MusicStyles, ponieważ jeden zespół może mieć wiele MusicStyles. – Peter

0
from ms in Context.MusicStyles 
where ms.Bands.Any(b => b.Name.Contains(search)) 
select ms; 

To po prostu zwraca styl, o co pyta twoje pytanie. Z drugiej strony przykładowy kod SQL zwraca styl i paski. Za to, że zrobię:

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

nie jest możliwe, aby po prostu zwrócić listę nowych obiektów, które zawierają elementy, które napisałem w moim SQL? – Peter

+0

Pewnie. Nie grupuj i zwróć anonimowy typ. Dodam przykład. –

1

Można zrobić wyżej, ale to przyniesie z powrotem wszystkie swoje wyniki po uruchomieniu iteracyjne nad nimi i filtrowanie odbywa się w pamięci, a nie na db.

Myślę, że to, czego szukasz, to tylko kilka złączeń?

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

lub coś w tym celu w każdym razie

+1

Problem polega na tym, że Linq To Entities nie daje właściwości dla kluczy obcych w twojej tabeli. Ponadto, nie istnieje taki system, jak BandMusicStyle, ponieważ łączy on tylko zespół i MusicStyle. – Peter

+0

Ah, nadal jestem w Linq w trybie Sql –

+0

Hej przynajmniej rozwiązałeś problem poprawnie, szkoda, że ​​nie używa on technologii, której potrzebuję ... – Peter

Powiązane problemy