Некоторые функции невозможно преобразовать в эквивалентные выражения? - PullRequest
2 голосов
/ 04 января 2012

Это продолжение вопроса, который я задал ранее, который можно увидеть здесь:

Запутался в передаче аргументов Expression vs. Func

Принятый там ответчик предлагает рефакторингВыражение, ссылающееся на локальные объекты во что-то, что Linq to Entities может фактически выполнить с резервным хранилищем (в моем случае SQL Server)

Я потратил много времени, пытаясь придумать что-то, что будет работать для того, что яя делаю.Мой оригинальный

Func<Thing, bool> whereClause

ссылался на локальный объект Dictionary, который Linq to Entities или SQL не мог понять во время выполнения.Я попытался рефакторинг в несколько списков, которые подделали словарь, и Массивы после этого.Каждый раз, когда я получал ошибки во время выполнения, жалуясь на то, что контекст не распознает такие вещи, как методы в List или индексаторы массива.

В конце концов я отказался и просто предоставил дополнительный метод, который принимает аргумент Func, когдаЯ не могу придумать правильное выражение.

Я не пытаюсь найти решение своей конкретной проблемы, я просто задаюсь вопросом в целом, можно ли всегда преобразовать,скажите

Func<Thing, bool>

эквивалентному

Expression<Func<Thing, bool>>

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

Ответы [ 2 ]

7 голосов
/ 04 января 2012

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

Expression<Func<string, int>> valid = text => text.Length;

Expression<Func<string, int>> invalid = text => { return text.Length; };

Существуют и другие ограничения.

Даже когда вы можете создать дерево выражений (а если вы сделаете это вручную, вы можете создать то, чего не будет компилятор C #, особенно в .NET 4), это не то же самое, что выражение дерево, представляющее что-то, что LINQ to SQL (и т. д.) может перевести соответствующим образом.

5 голосов
/ 04 января 2012

Джон, конечно, прав;вы превращаете лямбду в дерево выражений.

Чтобы немного расширить его ручную волну "различных других ограничений": лямбда, преобразованная в дерево выражений, может не содержать:

  • операторов
  • выражения, полезные главным образом для их мутаций состояния: операторы присваивания, составного присваивания, увеличения и уменьшения
  • динамические операции любого вида
  • инициализаторы многомерного массива
  • удаленные частичные методы
  • базовый доступ
  • операции с указателями любого вида
  • sizeof (T), за исключением случаев, когда T является встроенным типом
  • COM-Вызовы индексированных свойств стиля
  • Вызовы "необязательного ref" в стиле COM
  • Вызовы метода переменных C-стиля
  • Вызовы необязательных аргументов и именованных аргументов
  • группы методов (за исключением, конечно, при вызове)

Это не исчерпывающий список;Есть еще несколько странных угловых случаев.Но это должно охватывать большинство из них.

...