IQueryable для выражения с литералами - PullRequest
2 голосов
/ 24 мая 2011

Итак, у меня есть следующий сценарий, и я не уверен, как к нему приблизиться.

В приложении, которое мы создаем, у нас есть ReferenceDataService, который используется для загрузки данных через службы RIA. Запрос создается на клиенте как IQuerable и отправляется на сервер для извлечения. Сейчас большинство отправленных ссылочных запросов идентичны и вызываются несколько раз, поэтому я бы хотел вместо этого обслуживать эти запросы из кэша сущностей.

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

Chime.DataModel.classification[]
                .Where(c => ((value(Chime.Modules.Reference.Client.Agent.ReferenceDataLoader+<>c__DisplayClass20).includeSchema 
                        *AndAlso c.class_code.StartsWith(value(Chime.Modules.Reference.Client.Agent.ReferenceDataLoader+<>c__DisplayClass20).schema))* 
                        OrElse (Not(value(Chime.Modules.Reference.Client.Agent.ReferenceDataLoader+<>c__DisplayClass20).includeSchema) 
                        AndAlso *c.parent_code.StartsWith(value(Chime.Modules.Reference.Client.Agent.ReferenceDataLoader<>c__DisplayClass20).schema))))*
                .OrderByDescending(c => c.value_scheme_ind)
                .ThenBy(c => c.sequence_number)
                .ThenBy(c => c.class_label)

Так что я хотел бы на самом деле кешировать запрос, и если другой приходит с идентичными критериями, я могу попасть в кеш. У меня проблема в том, что литералы, используемые в запросе, по-видимому, недоступны, поэтому я не могу определить, отличается ли один запрос от другого. Например, кода схемы нигде нет. Он должен быть отправлен на сервер в какой-то момент, но я не уверен, как мне это сделать.

Кто-нибудь знает способ сделать это или сталкивался с этим раньше?

Dave

1 Ответ

2 голосов
/ 24 мая 2011

Если бы вы использовали WCF Data Services, я бы просто сказал, вызовите ToString () для вашего IQueryable, и он вернет точный URI запроса, который будет выполнен к службе данных ... и вы можете просто кешировать на основе этого строковое значение.

Насколько я знаю, RIA не предоставляет таких хуков, поэтому вам придется полагаться на более традиционные методы.

Реализуйте ExpressionVisitor, который посещает ваше IQueryable.Expression и вычисляет для него хеш-код.

Вы упомянули, что не можете видеть ваши постоянные строковые значения в дереве выражений. Это потому, что они еще не встроены в дерево выражений и, таким образом, все еще существуют как MemberAccessExpressions, а не ConstantExpressions. Чтобы исправить это, вы можете использовать частичную оценку ExpressionVisitor. Источник для таких дан здесь

http://msdn.microsoft.com/en-us/library/bb546158.aspx

Посмотрите на класс оценщика.

...