Как я могу построить запрос LINQ, когда тип объекта не известен во время компиляции - PullRequest
3 голосов
/ 03 февраля 2009

Я разрабатываю пользовательский элемент управления Web, который может применять фильтры к объекту LinqDataSource. Это общий контроль, поскольку он должен работать с объектом определенного типа.

Элемент управления знает, с каким полем объекта он должен работать, следующим полем

    /// <summary>
    /// Method to get compared column from object
    /// </summary>
    public Expression<Func<T, int>> GetColumnMethod;

(я передаю ему метод, который получает соответствующее поле из типа объекта)

Мы выполняем фильтрацию с таким кодом

... if (selectedValue == "<=") предикат = предикат. And (c => method (c) <= val); if (selectedValue == "<") предикат = предикат. And (c => method (c)

Все продолжается ОК, пока не произойдет преобразование LINQ to SQL. Тогда ошибка «Метод» ..... не поддерживает перевод на SQL.

конечно, CLR не знает, как создать SQL для делегатов.

Если бы только C # мог скомпилировать выражение перед переводом в SQL, но я понятия не имею, как это сделать.

Извращения, такие как Expression.Compile (какими бы хитрыми способами я ни занимался целый день - я уже не помню их всех ... ничего не помогло)

Но ... во время выполнения CLR уже знает тип моего объекта, поэтому он мог бы построить выражение SQL, скомпилировав значения делегатов. Но как это сделать ? Бог знает.

Помощь высоко ценится.

Ответы [ 4 ]

3 голосов
/ 03 февраля 2009

Поставщик LINQ to SQL отвечает за перевод дерева выражений в действительный оператор T-SQL. Поскольку между C # и T-SQL нет отношения 1: 1, весьма вероятно, что чем сложнее ваше дерево выражений, тем меньше вероятность того, что LINQ to SQL сможет перевести.

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

2 голосов
/ 03 февраля 2009

Это не сработает. По сути, ваш запрос LINQ является допустимым кодом C #, поэтому он прекрасно компилируется, но во время выполнения завершается сбоем на любом объекте, выходящем за рамки поставщика LINQ to SQL.

Подробнее здесь:

«Невозможно вызвать методы для DateTime» и другие ограничения

0 голосов
/ 03 февраля 2009

Нет SQL для произвольных делегатов. Если method(c) может быть выражено как лямбда, вы можете вызвать лямбду как подвыражение, используя Expression.Invoke, но вам нужно будет построить дерево выражений самостоятельно, , например, .

0 голосов
/ 03 февраля 2009

Если это просто вопрос выбора определенного поля для использования в вашем запросе, вы должны быть в состоянии сделать это, используя Expression.Compile "perversion". Но это, вероятно, будет много работы. Вероятно, вы можете получить преимущество, скомпилировав то, что у вас есть сейчас, и используя Reflector для вывода, чтобы посмотреть, как выглядит код, сгенерированный компилятором C #.

Можете ли вы разделить запрос на две части: одну, которая переводится в SQL и выполняется на сервере, а другую, которая использует ваш GetColumnMethod и работает в памяти с данными, полученными первой частью?

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