Здравствуйте, STDray, Вы писали:
STD>Итог: STD>1. нужен язык, поддерживающий вычисления в typelevel STD>2. размер генерируемого кода растет экспоненциально от числа условий и числа нуллабельных переменных (это только пример с Where разобрали) STD>3. при изменение запроса, весь зависимый код должен быть перекомпилирован STD>4. создание публичного интерфейса (типо паттерна "репозиторий") затруднено STD>5. непонятно, при чем здесь макросы
Это необязательно.
Краткий экскурс как обычно работает Linq to something:
1) Строится Expression Tree в рантайме (медленно)
2) ET имеет крайне неудобную структуру для обработки, фактически ты смотришь на выражение "снизу вверх", поэтому следующим шагом ET перестраивается к виду, похожему на исходный запрос. (достаточно быстро, но зависит)
3) Получившийся ET мапится на метаданные (медленно)
4) Генерируется SQL из ET с маппингом (быстро)
5) Выполняется SQL (медленно)
6) Результат мапится на объекты (медленно)
Так вот во всех современных провайдерах п3 и п6 ускоряются за счет кеширования. Фактически основная проблема с быстродействием на сегодня на п1 и п2.
П1 — это то, что генерит компилятор, и библиотеки в это вмешатся не могут. Было бы идеально, если бы прямо в процессе компиляции вместо ET генерировались более "легковесные" (читай не использующие рефлексию) деревья сразу с метаданными меппинга.
Усложняет все IQueryable<T>, так как это универсальный тип и вызов Select невозможно обработать не зная что там внутри IQueryable лежит.
Ну и пердобработку кешей для п3 и п6 тоже можно вынести в compile time. Хотя с п6 сложнее, на каждый тип может мапиться несколько запросов и до разбора дерева по сути неизвестно какой запрос это будет.