Płynne wyrażanie zapytań - czy jest jakaś przewaga jednej nad drugą?

255

LINQ jest jednym z największych ulepszeń .NET od czasów generycznych i pozwala mi zaoszczędzić mnóstwo czasu i linii kodu. Jednak płynna składnia wydaje mi się bardziej naturalna niż składnia wyrażenia zapytania.

var title = entries.Where(e => e.Approved)
    .OrderBy(e => e.Rating).Select(e => e.Title)
    .FirstOrDefault();

var query = (from e in entries
             where e.Approved
             orderby e.Rating
             select e.Title).FirstOrDefault();

Czy jest jakaś różnica między nimi, czy jest jakaś szczególna korzyść jednego nad drugim?

JarrettV
źródło
1
W przypadku złożonych zapytań uważam, że składnia lambda jest bardziej zrozumiała / czytelna, ale składnia zapytań jest po prostu ładniejsza.
nawfal

Odpowiedzi:

255

Nic nie jest lepsze: służą różnym potrzebom. Składnia zapytania pojawia się, gdy chcesz wykorzystać wiele zmiennych zakresu . Dzieje się tak w trzech sytuacjach:

  • Podczas używania słowa kluczowego let
  • Gdy masz wiele generatorów ( z klauzul)
  • Podczas wykonywania połączeń

Oto przykład (z próbek LINQPad):

string[] fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };

var query =
  from fullName in fullNames
  from name in fullName.Split()
  orderby fullName, name
  select name + " came from " + fullName;

Teraz porównaj to do tego samego w składni metody:

var query = fullNames
  .SelectMany (fName => fName.Split().Select (name => new { name, fName } ))
  .OrderBy (x => x.fName)
  .ThenBy  (x => x.name)
  .Select  (x => x.name + " came from " + x.fName);

Z drugiej strony składnia metody ujawnia pełną gamę operatorów zapytań i jest bardziej zwięzła z prostymi zapytaniami. Możesz uzyskać to, co najlepsze z obu światów, łącząc składnię zapytań i metod. Często odbywa się to w zapytaniach LINQ to SQL:

var query =
  from c in db.Customers
  let totalSpend = c.Purchases.Sum (p => p.Price)    // Method syntax here
  where totalSpend > 1000
  from p in c.Purchases
  select new { p.Description, totalSpend, c.Address.State };
Joe Albahari
źródło
2
Niezła odpowiedź. Czy możesz mi powiedzieć coś więcej o tym, co robi „.Select (name => new {name, fName})”?
quillbreaker
12
Wybiera pojedyncze słowo (anne, williams, john itp.) Wraz z pełnym imieniem i nazwiskiem anonimowym. Umożliwia to „noszenie” oryginalnej pełnej nazwy, dzięki czemu masz dostęp zarówno do pełnej nazwy, jak i pojedynczego słowa w pozostałej części zapytania.
Joe Albahari,
58

Wolę używać tego drugiego (czasami nazywanego „składnią rozumienia zapytań”), gdy mogę w ten sposób napisać całe wyrażenie.

var titlesQuery = from e in entries
                  where e.Approved
                  orderby e.Rating
                  select e.Titles;

var title = titlesQuery.FirstOrDefault();

Jak tylko muszę dodać (nawiasy) i .MethodCalls()zmieniam.

Kiedy używam tego pierwszego, zwykle umieszczam jedną klauzulę w wierszu, jak poniżej:

var title = entries
    .Where (e => e.Approved)
    .OrderBy (e => e.Rating)
    .Select (e => e.Title)
    .FirstOrDefault();

Uważam to za nieco łatwiejsze do odczytania.

Jay Bazuzi
źródło
29

Każdy styl ma swoje zalety i wady. Składnia zapytania jest ładniejsza, jeśli chodzi o sprzężenia i zawiera przydatne słowo kluczowe let, które ułatwia tworzenie zmiennych tymczasowych w zapytaniu.

Z drugiej strony płynna składnia ma o wiele więcej metod i operacji, które nie są ujawniane przez składnię zapytania. Ponieważ są to tylko metody rozszerzeń, możesz pisać własne.

Zauważyłem, że za każdym razem, gdy zaczynam pisać instrukcję LINQ przy użyciu składni zapytania, muszę ją umieścić w nawiasach i wracam do korzystania z płynnych metod rozszerzenia LINQ. Składnia zapytania po prostu nie ma wystarczającej liczby funkcji do samodzielnego użycia.

James Newton-King
źródło
„ponieważ są to tylko metody rozszerzeń, możesz pisać własne”. - napotkasz ten problem? stackoverflow.com/a/3850254/1175496
The Red Pea
20

W VB.NET bardzo wolę składnię zapytań.

Nienawidzę powtarzać brzydkiego słowa kluczowego Function:

Dim fullNames = { "Anne Williams", "John Fred Smith", "Sue Green" };
Dim query =
     fullNames.SelectMany(Function(fName) fName.Split().
     Select(Function(Name) New With {Name, fName})).
     OrderBy(Function(x) x.fName).
     ThenBy(Function(x) x.Name).
     Select(Function(x) x.Name & " came from " & x.fName)

To miłe zapytanie jest moim zdaniem znacznie bardziej czytelne i łatwe do utrzymania:

query = From fullName In fullNames
        From name In fullName.Split()
        Order By fullName, name
        Select name & " came from " & fullName

Składnia zapytań VB.NET jest również potężniejsza i mniej szczegółowa niż w języku C #: https://stackoverflow.com/a/6515130/284240

Na przykład to zapytanie LINQ do DataSet (Objects)

VB.NET:

Dim first10Rows = From r In dataTable1 Take 10

DO#:

var first10Rows = (from r in dataTable1.AsEnumerable() 
                   select r)
                   .Take(10);
Tim Schmelter
źródło
9
Moje współczucie dla programistów VB, którzy nie mogą używać stylu zapytań.
nawfal
1
Twój ostatni przykład w C # jest zbyt uproszczony, by był cenny: po prostu napiszesz `dataTable1.AsEnumerable (). Take (10);
Emyr,
@Emyr: mój ostatni akapit, który zaczyna się od „Składnia zapytań VB.NET jest również bardziej wydajna i mniej szczegółowa niż w języku C #”, po prostu porównuje składnię zapytań VB.NET z językiem C #, używasz składni metody.
Tim Schmelter,
15

W ogóle nie otrzymuję składni zapytania. Po prostu nie mam na to żadnego powodu. let można uzyskać za pomocą .Select i typów anonimowych. Po prostu myślę, że rzeczy wyglądają na znacznie lepiej zorganizowane z „interpunkcją”.

Instance Hunter
źródło
9
Wiele sprzężeń może być dość pracochłonne dzięki płynnej składni. Zasadniczo jednak używam płynnie - chyba że dołączone są połączenia.
Roman Starkov
1
@Instance Hunter: To samo tutaj. Długo zajęło mi zrozumienie płynnej składni. W połączeniu z potężnym, wymiennym i pomysłem „czystych” funkcji, teraz bardzo mi się to podoba, a wcześniej trudne sytuacje, które nie miały ładnej reprezentacji kodu. Dla Ye-Ole-SQL-części mózgu, nadal błogosławieństwem jest składnia zapytań.
Xan-Kun Clark-Davis
13

Płynny interfejs, jeśli tylko gdzieś. Jeśli potrzebuję polecenia select lub orderby, zazwyczaj używam składni zapytania.

James Curran
źródło
8

Płynna składnia wydaje się być naprawdę potężniejsza, powinna również lepiej działać, organizując kod w małe metody wielokrotnego użytku.

Kozyarchuk
źródło
5

Wiem, że to pytanie jest oznaczone C #, ale płynna składnia jest boleśnie wyczerpująca w VB.NET.

Larsenal
źródło
4

Bardzo podoba mi się płynna składnia i staram się jej używać tam, gdzie mogę, ale w niektórych przypadkach, na przykład, gdy używam złączeń, zwykle wolę składnię zapytania, w takich przypadkach łatwiej mi ją czytać i myślę, że niektórzy ludzie są bardziej zaznajomieni ze składnią zapytania (podobną do SQL) niż lambdas.

CMS
źródło
4

Rozumiem i podoba mi się płynny format, ale na razie trzymałem się Query ze względu na czytelność. Ludzie, którzy dopiero zapoznają się z LINQ, uznają Zapytanie za bardziej wygodne do czytania.

LizB
źródło
4

Wolę składnię zapytań, ponieważ pochodzę z tradycyjnego programowania WWW przy użyciu SQL. O wiele łatwiej jest mi owinąć głowę. Jednak wydaje mi się, że zacznę korzystać z .here (lambda), ponieważ jest zdecydowanie krótszy.

Steve Tranby
źródło
4

Używam Linq od około 6 miesięcy. Kiedy zacząłem go używać, wolałem składnię zapytania, ponieważ jest ona bardzo podobna do T-SQL.

Ale stopniowo przechodzę do tego pierwszego, ponieważ łatwo jest pisać fragmenty kodu wielokrotnego użytku jako metody rozszerzenia i po prostu połączyć je w całość. Chociaż uważam, że umieszczenie każdej klauzuli w osobnym wierszu bardzo pomaga w czytelności.

Antony Scott
źródło
3

Właśnie ustaliłem standardy naszej firmy i egzekwujemy stosowanie metod rozszerzenia. Myślę, że dobrym pomysłem jest wybranie jednego z drugiego i nie mieszanie ich w kodzie. Metody rozszerzeń czytają podobnie jak inny kod.

W składni rozumienia nie ma wszystkich operatorów i używanie nawiasów wokół zapytania i dodawanie metod rozszerzenia po prostu prosi mnie o użycie metod rozszerzenia od samego początku.

Ale w przeważającej części jest to tylko osobiste preferencje z kilkoma wyjątkami.

Rodi
źródło
3
Nie będę egzekwować osobistych preferencji. Ale to ja.
Memet Olsen