Pull to refresh

Comments 27

лично мне уже приходится намного сильнее напрягать мозг, чтобы разобраться что же это за pc, и что вообще здесь происходит

Для решения этой проблемы не нужно менять синтаксис. Поменяйте названия переменных ( p=>product, c=>category).

Более того, в сложных запросах типа Join с 4-5 аргументами, можно прописывать названия аргументов. Будет у вас что-то вроде

var result = products
    .Where(product => product.Price > 50) 
    .Join(categories, 
          outerKeySelector: product => product.CategoryId, 
          innerKeySelector: category => category.Id, 
          resultSelector: (product, category) => new { 
            ProductName = product.Name,
            CategoryName = category.Name,
            Price = product.Price 
          });

, только красиво подсвеченное в VS.

Согласен, ваш вариант намного понятнее, однако, довольно громоздко выходит. Да и

on product.CategoryId equals category.Id

для меня как-то проще читается, чем

outerKeySelector: product => product.CategoryId, 
innerKeySelector: category => category.Id, 

Хотя, возможно, я просто не достаточно к такому синтаксису привык.

Тоже никогда не понимал что за общепринятое пренебрежение названиями переменных при использовании Linq. Начинаешь сомневаться- может это я чего то не понимаю.

Скажу честно, я как правило тяготею к цепочке методов... Но только пока дело не доходит до джойнов. Особенно навроде left join-ов (хотя и inner join-ы тоже удобней в query syntax писать). В методном варианте это выглядит как-то уж совсем громоздко и неочевидно...

Как многие уже наверняка знают, LINQ - встроенный в C# язык запросов, которые появился аж в 2007 году (.NET Framework 3.5) и существует он в виде двух реализаций: Query-синтаксис (синтаксис запросов) и Method-синтаксис (синтаксис методов).

Несмотря на все возможности и достоинства синтаксиса запросов, он часто несправедливо игнорируется в пользу синтаксиса методов. 

В принципе в первом предложении ответ на вопрос из второго, почему он сейчас игнорируется. Потому что с 2007 года были добавлены более эффективные иснструменты, которые умеют все тоже, только обладают больше функциональностью и универсальностью, в том числе асинхронными вызовами.

Ну и для начинающих программистов, не особо знакомых с лямбда выражениями, Query синтаксис пониматься будет нааамного проще.

Ну и это тоже железный аргумент. Вместо того, чтобы учиться современным инструментам, вникать в делегаты, анонимные методы и операторы, лучше конечно работать с тем, чем проще.

Тут, наверное, ключевое слово "начинающий". Я неоднократно сталкивался с ситуацией, когда именно, ну совсем уж начинающие, достаточно тяжело усваивают то, что мне уже кажется таким элементарным, что аж бесит!!! Поэтому не нужно забывать, как мы сами изучали что-то "с нуля". Ведь изучить новую форму синтаксиса уже знакомого языка это не совсем одно и то же, что изучить "современные инструменты... делегаты и анонимные методы" человеку, не знающему еще ни одного языка... И как в любом обучении - всегда идут от простого к сложному...

Кстати. да, спасибо большое за идею для статьи с более высоким уровнем сложности - рассмотреть во что в итоге компилируются оба этих синтаксиса. Знаю, что в последних версиях шарпа LINQ неслабо так ускорили, интересно, касается ли это Query-syntax или только синтаксиса методов.

Можно ли пример инструментов более эффективных чем LINQ? Хочу расширить кругозор.

В компаниях где я работал использовался по сути только он в связке с EF Core. Хотя схожие запросы писались иначе чем в статье.

После группировки для фильтрации можно и не отходить от Query Syntax:

var filteredGroups = 
    from product in products
    join category in categories on product.CategoryId equals category.Id
    group product by category.Name into productGroup
    select new
    {
        CategoryName = productGroup.Key,
        AveragePrice = productGroup.Average(p => p.Price)
    } into s
    where s.AveragePrice > 100
    select s;

Согласен, можно было. Но нужно же было как-то показать совмещение двух синтаксисов. Тем более, что похоже примеры я не раз встречал в промышленном коде.

Для обоснования совмещения используйте Distinct. Его тупо нет в query синтаксе.

Вы абсолютно правы, поправил пример.

UFO just landed and posted this here

Вот это, кстати, мне тоже видится проблемой. Что для лучшее решение которое я знаю для реализации джойнов - написать свой метод расширения. Хотя и он не скажу, что сильно проще читается, чем синтаксис запросов.

UFO just landed and posted this here

Да, согласен. Просто хотел ещё раз напомнить, что в шарпе есть не только method syntax.

UFO just landed and posted this here

Для маленьких баз сойдет. а вот для больших больше проблем. Очень часто сгенерированый SQL код не ефективный и приходится писать ручками...

А какое это имеет отношение к статье? Тут расскащывается про различный синтаксис LINQ. Ни слова про EF и трансляцию LINQ в SQL

Непонятно почему не перенесут нормальный linq из F#. Он мощнее, быстрее и не генерит мусор.

Для простых запросов Method-синтаксис удобнее. Просто привыкнуть надо к лямбдам и вообще не шарахаться от чего-то сложнее foreach.)
Когда мне не хватало - пытался Query-синтаксис, получалось лучше, но это НЕ читабельно (мое мнение) и НЕ оптимально. Не хватает Method? EF разрешает в SQL, а дальше и до SP недалеко.
Если нужен Query - что-то в архитектуре вашего ПО не так явно.

Добавлю еще что Query-синтаксис еще и чужеродно выглядит.

У синтаксиса в стиле Query, на мой взгляд, самый большой недостаток это его похожесть на SQL. Эта похожесть путает тех кто знает SQL. Помечтаю немного, но было бы круто если бы Query синтаксис хотя бы для простых конструкций полностью совпадал бы с sql.

чтобы в GROUP BY пришлось дублировать списки полей, которые есть в SELECT?

Добрый день, я только недавно начал изучать EF и прекрасно понимаю что скорее всего я чего-то не понял в статье, по этому прошу объяснить в чем я не прав.

я так понимаю что для сложного запроса класс Product из простого запроса был модифицирован в

class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int CategoryId { get; set; }
}

Мои скромные познания заключаются в том что анонимные типы очень неудобны в дальнейшей разработке и я стараюсь их избегать если это возможно, по этому я бы модифицировал класс Product вот так:

class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int CategoryId { get; set; }
    public Category Category { get; set; }
}

при этом свойство CategoryId может быть создано самим EF как shadow property и удалено из класса, если оно используется только для связи таблиц

Для приведенного выше случая существует намного более удобный LINQ запрос и хотелось бы узнать преимущества Query-синтаксиса

var result = products
    .Include(p => p.Category)
    .Where(p => p.Price > 50);

P. S. Или хотелось бы узнать почему в приведенных в статье примерах класс Product не может иметь свойство Category

Ну во-первых, как уже говорили выше, в статье нет ни слова по еф. Ликью можно использовать не только для генерации скл-запросов, но и для работы со списками.

По поводу того, почему в продукте не оказалось категории:

Представьте себе ситуацию, когда вы получаете данные с двух систем. Эти системы знать не знают про друг дружку, но в одной из них в записях хранятся внешние ключи на записи из другой системы. И в таком случае, получив списки данных с обоих систем, нужно их сджонить, чтобы дальше осуществить какие-либо действия. Например, чтобы отобразить, если в действие происходит на клиенте, либо отдать в ответе, если это аггрегатор типа gateway

У query синтаксиса есть неочевидное преимущество: если погуглить "c# monad/fp/etc.", то в половине статей укажут на сходство select с do нотацией)

Sign up to leave a comment.