W T-SQL możesz mieć zapytanie takie jak:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
Jak zreplikowałbyś to w zapytaniu LINQ to Entities? Czy to w ogóle możliwe?
źródło
W T-SQL możesz mieć zapytanie takie jak:
SELECT * FROM Users WHERE User_Rights IN ("Admin", "User", "Limited")
Jak zreplikowałbyś to w zapytaniu LINQ to Entities? Czy to w ogóle możliwe?
Musisz obrócić go na głowie pod względem sposobu, w jaki myślisz o tym. Zamiast robić „in”, aby znaleźć prawa użytkownika dla bieżącego elementu w predefiniowanym zestawie odpowiednich praw użytkownika, pytasz o predefiniowany zestaw praw użytkownika, jeśli zawiera on odpowiednią wartość dla bieżącego elementu. W ten sam sposób można znaleźć element na zwykłej liście w .NET.
Można to zrobić na dwa sposoby za pomocą LINQ, jeden używa składni zapytania, a drugi - metody. Zasadniczo są one takie same i mogą być używane zamiennie w zależności od preferencji:
Składnia zapytania:
var selected = from u in users
where new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights)
select u
foreach(user u in selected)
{
//Do your stuff on each selected user;
}
Składnia metody:
var selected = users.Where(u => new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights));
foreach(user u in selected)
{
//Do stuff on each selected user;
}
Moją osobistą preferencją w tym przypadku może być składnia metody, ponieważ zamiast przypisywać zmienną, mógłbym wykonać foreach za pomocą anonimowego wywołania, takiego jak to:
foreach(User u in users.Where(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
Składniowo wygląda to na bardziej złożone i musisz zrozumieć pojęcie wyrażeń lambda lub delegatów, aby naprawdę zorientować się, co się dzieje, ale jak widać, skraca to sporo kod.
Wszystko sprowadza się do twojego stylu kodowania i preferencji - wszystkie trzy moje przykłady robią to samo nieco inaczej.
Alternatywny sposób nawet nie korzysta z LINQ, możesz użyć tej samej metody, zastępując „gdzie” słowem „FindAll” i uzyskać ten sam wynik, który będzie również działał w .NET 2.0:
foreach(User u in users.FindAll(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
To powinno wystarczyć do twojego celu. Porównuje dwie kolekcje i sprawdza, czy jedna kolekcja ma wartości pasujące do wartości w drugiej kolekcji
źródło
Jeśli używasz VS2008 / .net 3.5, zobacz wskazówkę Alexa Jamesa nr 8: http://blogs.msdn.com/alexj/archive/2009/03/26/tip-8-writing-where-in-style -queries-using-linq-to-entity.aspx
W przeciwnym razie wystarczy użyć metody array.Contains (someEntity.Member).
źródło
W tym kontekście wybiorę opcję dołączenia wewnętrznego. Gdybym użył zawierał, iterowałby 6 razy, mimo że fakt, że jest tylko jedno dopasowanie.
Wady zawartości
Załóżmy, że mam dwa obiekty listy.
Za pomocą Contains wyszuka każdą pozycję z Listy 1 na Liście 2, co oznacza, że iteracja nastąpi 49 razy !!!
źródło
Może to być możliwy sposób bezpośredniego użycia metod rozszerzenia LINQ w celu sprawdzenia klauzuli in
źródło
Próbowałem także pracować z rzeczą podobną do SQL-IN - zapytania do modelu danych jednostki . Moje podejście polega na tworzeniu ciągów znaków w celu skomponowania dużego wyrażenia OR. To okropnie brzydkie, ale obawiam się, że teraz jest to jedyna droga.
Teraz wygląda to tak:
Praca z identyfikatorami GUID w tym kontekście : jak widać powyżej, zawsze we fragmentach ciągu zapytania zawsze znajduje się słowo „GUID”. Jeśli tego nie dodasz,
ObjectQuery<T>.Where
zgłasza następujący wyjątek:Znalazłem to na forach MSDN, warto mieć to na uwadze.
Matthias
... czekamy na kolejną wersję .NET i Entity Framework, kiedy wszystko będzie lepiej. :)
źródło
Alternatywna metoda dla odpowiedzi BenAlabaster
Przede wszystkim możesz przepisać zapytanie w następujący sposób:
Z pewnością jest to bardziej „niewygodne” i trudne do napisania, ale działa tak samo.
Gdybyśmy mieli jakąś użyteczną metodę, która ułatwiłaby tworzenie tego rodzaju wyrażeń LINQ, bylibyśmy w biznesie.
za pomocą metody narzędziowej możesz napisać coś takiego:
To buduje wyrażenie, które ma taki sam efekt jak:
Ale co ważniejsze, faktycznie działa przeciwko .NET 3.5 SP1.
Oto funkcja hydrauliczna, która umożliwia:
Nie zamierzam wyjaśniać tej metody, poza tym, że zasadniczo buduje wyrażenie predykatu dla wszystkich wartości za pomocą valueSelector (tj. P => p.User_Rights) i OR tych predykatów razem, aby utworzyć wyrażenie dla kompletności orzec
Źródło: http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx
źródło
Prawdziwy przykład:
źródło
Poważnie? Wy nigdy nie korzystaliście
źródło
Checks = NumValues * NumRows
. Ponieważ jest to obliczenie typu M * N, jeśli jedno z nich jest małe, czas wykonania każdej wymaganej kontroli również będzie krótki. Dodałem ograniczenie, aby cjm30305 wiedział, jak skonfigurować środowisko testowe, w którym pokaże, dlaczego jego rozwiązanie jest słabe.where new[] { 1, 2, 3 }.Contains(x)
wtedy mniej porównańwhere (x == 1 || x == 2 || x == 3)
?