Позвольте мне начать с указания, что неважно, компилируете ли вы свой запрос или нет. Вы могли бы наблюдать те же самые результаты, даже если вы не выполняли предварительную компиляцию.
Технически, как отметил Эндрю, сделать эту работу не так уж сложно. Когда ваше выражение LINQ оценивается, дерево выражений создается внутренне. Ваша функция отображается как узел в этом дереве выражений. Никакой магии здесь. Вы сможете написать это выражение как в L2S, так и в L2E, и оно будет компилироваться и работать нормально. Это происходит до тех пор, пока вы не попытаетесь фактически выполнить фактический запрос SQL к базе данных. Вот где начинается разница. L2S, похоже, успешно выполняет эту задачу, тогда как L2E завершается с ошибкой NotSupportedException и сообщает, что не знает, как преобразовать ToThema в запрос хранилища.
Так что же происходит внутри? В L2S, как объяснил Эндрю, компилятор запросов понимает, что ваша функция может быть запущена отдельно от того, как был выполнен запрос хранилища. Таким образом, он отправляет вызовы вашей функции в конвейер чтения объектов (где данные, прочитанные из SQL, преобразуются в объекты, возвращаемые в результате вашего вызова).
Когда-то Эндрю не совсем прав, это то, что важно то, что находится внутри вашего статического метода. Я не думаю, что это так.
Если вы поставите точку останова в отладчике для своей функции, вы увидите, что она вызывается один раз для возвращаемой строки. В трассировке стека вы увидите «облегченную функцию», которая в действительности означает, что метод был запущен во время выполнения. Так вот как это работает для Linq to Sql.
Команда Linq to Entity, похоже, шла другим путем. Я не знаю, в чем причина, почему они решили запретить все Invocation Expressions из запросов L2E. Возможно, это было связано с производительностью или может быть связано с необходимостью поддержки всех типов поставщиков, а не только SQL Server, чтобы устройства чтения данных могли вести себя по-разному. Или они просто подумали, что большинство людей не поймут, что некоторые из них выполняются для каждой возвращаемой строки, и предпочли оставить эту опцию закрытой.
Только мои мысли. Если у кого-то есть еще понимание, пожалуйста, присоединяйтесь!