Linq-запрос на IDictionaryEnumerator Возможно? - PullRequest
4 голосов
/ 01 февраля 2011

Мне нужно очистить элементы из кэша, которые содержат определенную строку в ключе. Я начал со следующего и подумал, что смогу выполнить запрос linq

var enumerator = HttpContext.Current.Cache.GetEnumerator();

Но я не могу? Я надеялся сделать что-то вроде

var enumerator = HttpContext.Current.Cache.GetEnumerator().Key.Contains("subcat");

Есть идеи, как мне этого добиться?

Ответы [ 3 ]

10 голосов
/ 01 февраля 2011

Перечислитель, созданный Cache, генерирует DictionaryEntry объекты. Кроме того, Cache может иметь только string клавиш.

Таким образом, вы можете написать следующее:

var httpCache = HttpContext.Current.Cache;
var toRemove = httpCache.Cast<DictionaryEntry>()
    .Select(de=>(string)de.Key)
    .Where(key=>key.Contains("subcat"))
    .ToArray(); //use .ToArray() to avoid concurrent modification issues.

foreach(var keyToRemove in toRemove)
    httpCache.Remove(keyToRemove);

Однако, если кеш большой, это потенциально медленная операция: кеш не предназначен для такого использования. Вы должны спросить себя, не является ли альтернативный дизайн невозможным и предпочтительным. Почему вам нужно удалить несколько ключей кэша одновременно, и почему вы не группируете ключи кэша по подстроке?

5 голосов
/ 01 февраля 2011

Поскольку Cache является IEnumerable, вы можете свободно применять все необходимые для него методы LINQ.Единственное, что вам нужно, это привести его к IEnumerable :


var keysQuery = HttpContext.Current.Cache
    .Cast<DictionaryEntry>()
    .Select(entry => (string)entry.Key)
    .Where(key => key.Contains("subcat"));

Теперь keysQuery - это нестрогая коллекция всех ключей, начиная с «subcat».Но если вам нужно удалить такие записи из кэша, самый простой способ - просто использовать оператор foreach.

2 голосов
/ 01 февраля 2011

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

    var iter = HttpContext.Current.Cache.GetEnumerator();
    using (iter as IDisposable)
    {
        while (iter.MoveNext())
        {
            string s;
            if ((s = iter.Key as string) != null && s.Contains("subcat"))
            {
                //... let the magic happen
            }
        }
    }

, чтобы сделать этос LINQ вы можете сделать что-то вроде:

public static class Utils
{
    public static IEnumerable<KeyValuePair<object, object>> ForLinq(this IDictionaryEnumerator iter)
    {
        using (iter as IDisposable)
        {
            while (iter.MoveNext()) yield return new KeyValuePair<object, object>(iter.Key, iter.Value);
        }
    }
}

и использовать как:

var items = HttpContext.Current.Cache.GetEnumerator().ForLinq()
       .Where(pair => ((string)pair.Key).Contains("subcat"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...