Mam problem z zapytaniem napisanym w LINQ i Lambda. Do tej pory otrzymuję wiele błędów, oto mój kod:
int id = 1;
var query = database.Posts.Join(database.Post_Metas,
post => database.Posts.Where(x => x.ID == id),
meta => database.Post_Metas.Where(x => x.Post_ID == id),
(post, meta) => new { Post = post, Meta = meta });
Jestem nowy w używaniu LINQ, więc nie jestem pewien, czy to zapytanie jest poprawne.
Odpowiedzi:
Uważam, że jeśli znasz składnię SQL, użycie składni zapytania LINQ jest znacznie wyraźniejsze, bardziej naturalne i ułatwia wykrywanie błędów:
Jeśli jednak naprawdę utknąłeś przy użyciu lambdas, twoja składnia jest dość odległa. Oto to samo zapytanie, przy użyciu metod rozszerzenia LINQ:
źródło
lambda
cytatu jest łatwy w użyciu i zrozumiałyMożna to zrobić na dwa sposoby. Korzystając z LINQPad (nieoceniony, jeśli dopiero zaczynasz korzystać z LINQ) i sztucznej bazy danych, stworzyłem następujące zapytania:
lub
W tym konkretnym przypadku myślę, że składnia LINQ jest czystsza (zmieniam się między nimi w zależności od tego, który jest najłatwiejszy do odczytania).
Chciałbym jednak zauważyć, że jeśli masz odpowiednie klucze obce w bazie danych (między post a post_meta), prawdopodobnie nie potrzebujesz jawnego łączenia, chyba że próbujesz załadować dużą liczbę rekordów . Twój przykład wydaje się wskazywać, że próbujesz załadować pojedynczy post i jego metadane. Zakładając, że dla każdego postu istnieje wiele rekordów post_meta, możesz wykonać następujące czynności:
Jeśli chcesz uniknąć problemu n + 1, możesz jawnie powiedzieć LINQ do SQL, aby ładował wszystkie powiązane elementy za jednym razem (chociaż może to być zaawansowany temat, gdy lepiej znasz L2S). Poniższy przykład mówi „gdy ładujesz Post, załaduj również wszystkie powiązane z nim rekordy za pomocą klucza obcego reprezentowanego przez właściwość„ Post_metas ”:
Możliwe jest wykonywanie wielu
LoadWith
połączeń na jednym zestawieDataLoadOptions
dla tego samego typu lub wielu różnych typów. Jeśli robisz to dużo, możesz po prostu rozważyć buforowanie.źródło
Daniel ma dobre wyjaśnienie związków między składniami, ale złożyłem ten dokument dla mojego zespołu, aby ułatwić im zrozumienie. Mam nadzieję, że to komuś pomoże
źródło
Post_ID
pole w drugim aliasiemeta => meta.Post_ID
. W przykładzie na tej ilustracjig.id
część oryginalnej instrukcji selectJOIN gStatus g on g.id
nie jest replikowana w końcowym wyrażeniu Lambda.public class IdHolder{ int id }
a następnie użył tego obiektu w gStatus,List<IdHolder> gStatus = new List<IdHolder>(); gStatus.add(new IdHolder(){id = 7}); gStatus.add(new IdHolder(){id = 8});
wówczas zmieniłby Linqa na taki,t =>t.value.TaskStatusId, g=>g.id
czy ta zmiana ma sens?Twoje selektory kluczy są nieprawidłowe. Powinny wziąć obiekt typu tabeli, o której mowa, i zwrócić klucz do użycia w złączeniu. Myślę, że masz na myśli to:
Możesz zastosować klauzulę where później, a nie jako część selektora kluczy.
źródło
Publikowanie, ponieważ kiedy uruchomiłem LINQ + EntityFramework, patrzyłem na te przykłady przez jeden dzień.
Jeśli używasz EntityFramework i masz skonfigurowaną właściwość nawigacji nazwaną
Meta
wPost
ustawionym obiekcie modelu, jest to łatwe. Jeśli korzystasz z encji i nie masz tej właściwości nawigacji, na co czekasz?Jeśli najpierw tworzysz kod, możesz skonfigurować właściwość w następujący sposób:
źródło
Zrobiłem coś takiego;
źródło
To może być coś takiego
źródło
1 oznacza 1 dwa różne łączenie stołu
źródło
To zapytanie linq powinno działać dla Ciebie. Otrzyma wszystkie posty, które mają meta postu.
Równoważne zapytanie SQL
źródło