Здравствуйте, alex_public, Вы писали:
_>Ну почему же, вполне себе в нашей общей: http://www.tiobe.com/tiobe_index?page=index. О, я смотрю уже и мой любимый Питончик обошёл C#, забавненько... )))
Эти тесты похоже из твоей же реальности. Например, я уже лет 8 не видел и ничего не слыашал о таком редком звере как VB девелопер. А здесь он аж в десятке. О VB много пишут, это да, но пишут _о_ нём, а не _на_ нём. К тому же я ещё не разу не видел, чтобы C# шёл в рост. Он всё время падает с самого свого рождения. Т.е. с самого нуля падает и пока ещё до нуля не упал. Как такое может быть не пойму. Видимо в ваших реальностях это нормально.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
IT>>Во-вторых, совсем совсем статические запросы — это далеко не все запросы в приложении. EP>Сколько статических по твоим оценкам?
Думаю, где-то 50/50 по количеству. Но статические запросы как правило простые. Динамические могут занимать не одну страницу кода.
IT>>Часто приходится формировать запросы динамически. EP>Чем это конкретно обусловлено?
Бизнес логикой.
EP>Я к тому, что если это обусловлено например тем что итоговый запрос собирается в разных частях программы (о чём в этих темах часто и говорят), то для этого динамика не обязательна.
Поясни.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, alex_public, Вы писали:
_>В приведённом тобой тесте идёт сравнение исполнения через linq2db запроса записанного через linq с исполнением через ADO запроса записанного текстовой строкой. Такое сравнение не может быть использовано при обсуждение вопроса накладных расходов вносимых записью запроса через linq (почему подробно объяснено в предыдущих сообщениях данной темы).
Ты же когда говорил про 90% сравнивал LINQ именно с ADO.NET, а теперь вдруг ловишь меня на нечестности. Я даже одной секунды на эту фигню тратить не буду. Тем более, что результат будет ещё больше в пользу LINQ.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, IT, Вы писали:
IT>>Во-вторых, совсем совсем статические запросы — это далеко не все запросы в приложении. EP>Сколько статических по твоим оценкам?
По моим оценкам 0.
Потому что предикаты в одних функциях, а проекции в других.
Или ты что-то другое посчитать хочешь?
EP>Я к тому, что если это обусловлено например тем что итоговый запрос собирается в разных частях программы (о чём в этих темах часто и говорят), то для этого динамика не обязательна.
Покажи пример как сделать, чтобы была необязательна. Пока этого никому не удалось.
Здравствуйте, IT, Вы писали:
IT>>>Часто приходится формировать запросы динамически. EP>>Чем это конкретно обусловлено? IT>Бизнес логикой.
Небольшой пример?
EP>>Я к тому, что если это обусловлено например тем что итоговый запрос собирается в разных частях программы (о чём в этих темах часто и говорят), то для этого динамика не обязательна. IT>Поясни.
ЕМНИП, где-то в этой, или аналогичной теме было мнение, что мол для собирания запроса по кускам необходима динамика.
На самом деле тут динамика не обязательна. Например:
Здравствуйте, gandjustas, Вы писали:
IT>>>Во-вторых, совсем совсем статические запросы — это далеко не все запросы в приложении. EP>>Сколько статических по твоим оценкам? G>По моим оценкам 0. G>Потому что предикаты в одних функциях, а проекции в других.
Чуть выше я как раз привёл пример именно на эту тему, там полная статика.
EP>>Я к тому, что если это обусловлено например тем что итоговый запрос собирается в разных частях программы (о чём в этих темах часто и говорят), то для этого динамика не обязательна. G>Покажи пример как сделать, чтобы была необязательна. Пока этого никому не удалось.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Небольшой пример?
Например, поисковые формы. Есть 50 колонок для фильтрации запроса, а в результирующем гриде есть возможность выбирать отображаемые колонки. Под фильтрацией понимается не только фильтрация колонок в мастер таблице, но и фильтрация по колонкам связанных таблиц.
EP>В выделенном месте есть вся необходимая информация для построения запроса во время компиляции, то есть для такого сценария динамика не требуется.
Это не динамика. Это декомпозиция. Вот динамика:
var q = db.Table1;
if (a != null)
q = q.Where(t => t.Field1 == a);
if (b > 3)
q = q.Where(t => t.Table2.Field2 != 15);
else
q = q.Where(t => t.Table3.Field7.In("z", "y", "z"));
q.ToList();
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
EP>>Небольшой пример? IT>Например, поисковые формы. Есть 50 колонок для фильтрации запроса, а в результирующем гриде есть возможность выбирать отображаемые колонки. Под фильтрацией понимается не только фильтрация колонок в мастер таблице, но и фильтрация по колонкам связанных таблиц.
Да, тут динамика, причём здесь предварительно генерировать все варианты не разумно, ибо их очень много.
EP>>В выделенном месте есть вся необходимая информация для построения запроса во время компиляции, то есть для такого сценария динамика не требуется. IT>Это не динамика. Это декомпозиция.
Согласен. Но вот gandjustas выше именно это и назвал динамикой, о чём я и говорил.
IT>Вот динамика: IT>
auto q1 = context.Employees;
auto q2 = conditional(!IsNullOrEmpty(lastName), q1.Where(e.LastName = lastName));
auto q3 = conditional(!IsNullOrEmpty(firstName), q2.Where(e.FirstName= firstName));
auto q4 = conditional(HasValue(employmentDateFrom), q3.Where(e.EmploymentDate >= employmentDateFrom.Value));
auto q5 = conditional(HasValue(employmentDateTo)), q4.Where(e.EmploymentDate <= employmentDateTo.Value));
//далее в Presentation Layer (в другом месте)auto list = await q5.Take(pageSize).Select(/*projection*/).ToListAsync();
При попытке выполнить этот запрос, будет произведено 4 runtime проверки, в результате чего будет выбрана одна из 16 сгенерированных в compile-time версий запроса (причём которые могут кардинально отличаться друг от друга).
Если не нравится экспоненциальное количество запросов в исполняемом файле, то можно добавить динамики. Да, при этом запрос будет частично строится в runtime (с возможным кэшированием), но при этом не будет дорогой runtime reflection — в ней тут нет принципиальной необходимости, достаточно compile-time reflection.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Такие запросы тоже можно сгенерировать во время компиляции — вопрос в количестве вариантов.
В этом нет смысла. Единственная проблема ET — это сложность получения хешь функции самого дерева, т.к. оно перестраивается компилятором при каждом вызове. Если делать свой собственный DSL, то такую возможность можно предусмотреть и тогда проблема кеширования запросов отпадает. Т.е. не стоит выпрыгивать из штанов в compile-time, получая неполноценный результат. Можно легко закешировать результат в run-time и жить счастливо.
Кстати, у linq2db накладные расходы на построение запроса значительно меньше остальных провайдеров только потому, что результат разбора ET кешируется. Остальные провайдеры почему-то эту возможность дружно игнорируют.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
EP>>Такие запросы тоже можно сгенерировать во время компиляции — вопрос в количестве вариантов. IT>В этом нет смысла. Единственная проблема ET — это сложность получения хешь функции самого дерева, т.к. оно перестраивается компилятором при каждом вызове. Если делать свой собственный DSL, то такую возможность можно предусмотреть и тогда проблема кеширования запросов отпадает. Т.е. не стоит выпрыгивать из штанов в compile-time, получая неполноценный результат.
Не спорю, возможно и не стоит.
Я лишь говорю о том, что многие преимущества linq, в том числе и то что ты называешь главным козырем — type-safety, можно получить через генерацию compile-time, даже для динамических запросов. Насколько же это целесообразно — отдельный и важный вопрос.
IT>Можно легко закешировать результат в run-time и жить счастливо.
Размер кэша нужно ограничивать, иначе на долгоиграющей программе может вылезти та же самая комбинаторика. А раз размер ограничен, то будут переодические перевычисления вымытого из кэша.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Пример выше.
1) Так ты покажи макрос conditional или что там у тебя. А то так можно любой код написать и объявить его "статическим".
2) Как делать декомпозицию \ композицию таких запросов? В идеале так:http://blog.gandjustas.ru/2010/05/30/iqueryable-generics/
3) Как ты реализуешь такой сценарий:
...
where x.y in (@p1, @p2,...) -- количество значений в in будет зависеть от исходного массива
?
4) Как ты сделаешь провайдеры под разные БД? (на этом alex_public посыпался)
5) Будет ли возможность сделать запрос динамическим, чтобы, например, проекция зависела от выбранных значений? Часто используется в UI и Odata сервисах.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Не спорю, возможно и не стоит. EP>Я лишь говорю о том, что многие преимущества linq, в том числе и то что ты называешь главным козырем — type-safety, можно получить через генерацию compile-time, даже для динамических запросов.
Никто и не спорит. Повторюсь. LINQ не является идеальным решением, но на сегодняшний день это лучшее решение. Лучшее потому что полностью поддерживается компилятором, а это не только type-safety, но ещё и полноценная поддержка средствами разработки.
IT>>Можно легко закешировать результат в run-time и жить счастливо.
EP>Размер кэша нужно ограничивать, иначе на долгоиграющей программе может вылезти та же самая комбинаторика. А раз размер ограничен, то будут переодические перевычисления вымытого из кэша.
Да это вообще не вопрос. В linq2db, если мне правильно подсказывает мой склероз, порядка 100 запросов на возвращаемый тип. Да и на самом деле, в обычном приложении количество различных запросов измеряется в лучшем случае несколькими сотнями. А чаще несколькими десятками.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, gandjustas, Вы писали:
EP>>>Пример выше. G>>Так ты покажи макрос conditional или что там у тебя.
EP>Функция conditional была в сообщении после того, на которое ты отвечаешь. EP>Я имел в виду вот этот код
G>Какой тип возвращает where? Какой тип возвращает part1()?
Тип в который в том числе закодировано дерево выражения. На C++ это реализуется с помощью техники Expression Templates, которой уже более двадцати лет.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Тип в который в том числе закодировано дерево выражения. На C++ это реализуется с помощью техники Expression Templates, которой уже более двадцати лет.
Показывай минимально работающий пример, который обходит дерево и строит SQL. Потому что построить дерево на шаблонах несложно. Самое интересное начинается дальше.
Кроме того сразу видна проблема. У тебя слишком коноетный тип, композицию сложно будет делать.
То есть from | where | select имеет тип select<where<from>>, как написать аналог функции
Здравствуйте, gandjustas, Вы писали: G>1) Так ты покажи макрос conditional или что там у тебя. А то так можно любой код написать и объявить его "статическим".
Я же не просто объявил, а описал механизм:
EP>При попытке выполнить этот запрос, будет произведено 4 runtime проверки, в результате чего будет выбрана одна из 16 сгенерированных в compile-time версий запроса (причём которые могут кардинально отличаться друг от друга).
Мощности шаблонов для реализации такого механизма достаточно.
Нечто схожее я реализовал вот тут
— во время компиляции строятся все варианты графа отношения порядка между элементами массива фиксированного размера, генерируется код для сортирующей перестановки каждого из вариантов, далее в runtime производятся необходимые сравнения элементов массива для выбора конкретного из всех графов, и вызов соответствующей ему перестановки. G>2) Как делать декомпозицию \ композицию таких запросов? В идеале так:http://blog.gandjustas.ru/2010/05/30/iqueryable-generics/
В статье описана борьба с неким ограничением LINQ.
На C++ нет проблемы вынести выделенную часть из выражения
something.Where(o => o.Visible)
в отдельную сущность и прилепить её к чему угодно. Пример:
G>...
G>where x.y in (@p1, @p2,...) -- количество значений в in будет зависеть от исходного массива
G>
G>?
Структура запроса не меняется, поэтому достаточно сгенерировать в runtime только вот эту часть @p1, @p2,... G>4) Как ты сделаешь провайдеры под разные БД? (на этом alex_public посыпался)
В чём конкретно вопрос?
Например если про несколько провайдеров используемых одновременно — то придётся генерировать запросы для каждого, и выбирать нужный. G>5) Будет ли возможность сделать запрос динамическим, чтобы, например, проекция зависела от выбранных значений? Часто используется в UI и Odata сервисах.
Да, такую возможность можно прикрутить. В любом месте где целесообразна динамика — её можно реализовать, со всеми вытекающими.
Интересный у вас спор. Между реальной действующей системой Linq to SQL и возможностями С++.
Берется например любая конфигурация 1С и на ней тестятся все возможности Linq to EF например http://infostart.ru/public/402038/
И аналог Linq на С++. И сравниваются возможности.
Например Code First и Linq to EF на примере 1С версии 8.3 часть II
А то у вас сравнение с сферическим конем. Возможности и реальная система это разные вещи.
C++ мощный язык, но он так же и значительно сложнее того же C#. Не говоря уже об 1С.
Можно создать кучу приблуд, только кто на нём буде программировать?
А вот на 1С программирует куча народу. В том числе потому, что язык под это заточен.
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Интересный у вас спор. Между реальной действующей системой Linq to SQL и возможностями С++.
Вообще-то не с возможностями C++, а с возможной альтернативной реализацией. На каком именно языке — C++, D, Nemerle, Rust, etc — не суть важно.
S>Берется например любая конфигурация 1С и на ней тестятся все возможности Linq to EF например S>http://infostart.ru/public/402038/ S> И аналог Linq на С++. И сравниваются возможности.
Я не собираюсь реализовывать аналог linq + linq2db на C++ — мне это не интересно, у меня сейчас вообще нет никаких задач связанных БД
S>Возможности и реальная система это разные вещи.
Здравствуйте, gandjustas, Вы писали:
EP>>Тип в который в том числе закодировано дерево выражения. На C++ это реализуется с помощью техники Expression Templates, которой уже более двадцати лет. G>Показывай минимально работающий пример, который обходит дерево и строит SQL.
Показывающий что конкретно? Проекции? Фильтры? Автоматические join'ы по связям?
Это всё ни одна сотня строк кода, реализовать которые мне не интересно.
G>Потому что построить дерево на шаблонах несложно. Самое интересное начинается дальше.
Что именно тебя смущает? Говори конкретный аспект и я расскажу (и возможно покажу) каким образом он реализуется
G>Кроме того сразу видна проблема. У тебя слишком коноетный тип
Это плата за статику.
G>, композицию сложно будет делать. G>То есть from | where | select имеет тип select<where<from>>, как написать аналог функции G>