2009-04-17 3 views
2

Я работаю над созданием некоторого псевдо-интеллектуального кэширования в LINQ query provider. Я бы хотел (в идеале) использовать дерево выражений заданного запроса в качестве ключа кеша в некоторых сценариях. Тем не менее, я не хочу хранить весь объектный граф сам, так что быстрый способ получить значение hashsum-like из дерева выражений? Или, если я пойду в неправильном направлении, есть ли лучший вариант?Хеширование дерева выражений

ответ

-1

Ум, на самом деле я думаю, что это может быть довольно просто.

Метод ToString() объекта Expression предоставит вам текстовое представление выражения, вы можете сделать хэш, если все, что вам нужно, - это оценить эквивалентность ключа.

+1

Это не включает полный хэш дерева выражений ... и многие деревья выражений имеют одинаковые строковое значение, но различные базовые узлы. Есть ли у вас какие-либо предложения? Мне тоже нужно это сделать. Я думаю о том, чтобы сделать посетителя хеширования, который специально знает, чтобы включить и вызвать GetHashCode на базовые значения ConstantExpressions. Как вы думаете? – Jeff

+0

Я понял, что это полный текст дерева выражений, например, это то, что я получаю с запросом с предложением where и значением проекции ..... (Quest.Intersect.Core.DataHubQueryableTable'1 [Quest .Intercept.TestHarness.Customer]). Где (cust => (cust.LastName = "jarvis")). Выберите (cust => new <> f__AnonymousType1'2 (CompID = cust.CompanyID, LastName = cust.LastName)) –

+0

Как вы можете видеть, это содержит оцененные константы плюс анонимный класс и т. Д. Мне кажется, что хэш этого будет достаточно хорошим ключом в словаре ... однако, сказав, что альтернатива, как вы полагаете, будет создав посетителя, который создал составной хэш каждого узла/листа. –

1

Давайте подумаем об этом. Предположительно, вы хотите сохранить (хэш дерева выражений, результат) на карте.

Без сохранения всего дерева вы не можете различать идентичное дерево и столкновение хэшей.

По определению хешируют более крупный набор на меньший набор (поэтому полезен хеш), поэтому по определению у вас будут (по крайней мере, возможность) столкновения.

Когда вы получаете дерево выражения, вы хэширования, а затем посмотрите на результат в вашей карте, что приводит к двум возможностям:

  1. это хэш не в карте, тот, который вы не видели раньше. Вы должны позволить этому запустить, так как у вас нет кэшированного результата.

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

Кроме того, даже если это не столкновение, даже если это точно такое же выражение дерева, как тот, который вы видели в последний раз, как мы знаем, что поддержка объект - база данных, список, независимо от * не было элементов, добавленных или удаленных или измененных, так что результат, возвращаемый выражением, может отличаться от результата кэширования?

Тем не менее, вы можете хэш дерева рекурсивно:

hashATree: 
if leaf node 
    return hash(node) 
else 
    return hash(node) *OP* hashATree(left.child) *OP* hashATree(right.child) 

где OP является некоторой операции (возможно умножение), или, в более общем hash(node) *OP* accumulate(children.begin(), children.end(), *OP*);

Конечно, это же рекурсии мы использовать для оценки дерева выражений (ожидаем, мы позвоним node.eval(children);)

+0

Для nitpick хеши не всегда идут от большого набора к небольшому набору, EG-хэши. – RossFabricant

+0

Ваша точка зрения о столкновениях теоретически правильна, но также практически не имеет значения.MD5 и SHA также имеют потенциал для столкновений, но мы все еще используем их, потому что они практичны. Мне нужен практический хеш, а не математический коллизионный хэш. –

+0

Чтобы ответить на ваш вопрос о проблемах синхронизации с хранилищем, я решил эти проблемы. Тем не менее, я не чувствую себя комфортно в производстве с помощью моего текущего метода кеширования (хранения самого дерева выражений) –

1

Возможно, вы можете сделать это, используя представленный здесь код. http://petemontgomery.wordpress.com/2008/08/07/caching-the-results-of-linq-queries/

Это показывает, как решить проблему закрытия и поддерживает локальные коллекции.

+0

Если бы вы могли включить в него соответствующие биты, это было бы здорово. Люди приходят сюда для ответов, а не ссылок ... и если вы не можете гарантировать, что ваш блог будет навсегда, этот ответ станет бесполезным, если он когда-либо снизится. – cHao

+0

Ну, в основном он использует '.ToString()'. –

Смежные вопросы