Кеширование в консольном приложении - PullRequest
16 голосов
/ 29 сентября 2011

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

Ответы [ 7 ]

15 голосов
/ 29 сентября 2011

Сохранить как экземпляр экземпляра содержащего класса.В веб-приложении вы не можете этого сделать, поскольку объект класса страницы воссоздается при каждом запросе.

Однако .NET 4.0 также имеет MemoryCache класс для этой цели.

7 голосов
/ 29 сентября 2011

В переменной уровня класса.Предположительно, в методе main вашего консольного приложения вы создаете экземпляр хотя бы одного объекта.В классе этого объекта вы объявляете переменную уровня класса (List<String> или любую другую), в которой вы кэшируете все, что требует кэширования.

3 голосов
/ 22 января 2014

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

Использование:

return Cache.Get("MyCacheKey", 30, () => { return new Model.Guide().ChannelListings.BuildChannelList(); });

Класс:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Timers;

    namespace MyAppNamespace
    {
        public static class Cache
        {
            private static Timer cleanupTimer = new Timer() { AutoReset = true, Enabled = true, Interval = 60000 };
            private static readonly Dictionary<string, CacheItem> internalCache = new Dictionary<string, CacheItem>();

            static Cache()
            {
                cleanupTimer.Elapsed += Clean;
                cleanupTimer.Start();
            }

            private static void Clean(object sender, ElapsedEventArgs e)
            {
                internalCache.Keys.ToList().ForEach(x => { try { if (internalCache[x].ExpireTime <= e.SignalTime) { Remove(x); } } catch (Exception) { /*swallow it*/ } });
            }

            public static T Get<T>(string key, int expiresMinutes, Func<T> refreshFunction)
            {
                if (internalCache.ContainsKey(key) && internalCache[key].ExpireTime > DateTime.Now)
                {
                    return (T)internalCache[key].Item;
                }

                var result = refreshFunction();

                Set(key, result, expiresMinutes);

                return result;
            }

            public static void Set(string key, object item, int expiresMinutes)
            {
                Remove(key);

                internalCache.Add(key, new CacheItem(item, expiresMinutes));
            }

            public static void Remove(string key)
            {
                if (internalCache.ContainsKey(key))
                {
                    internalCache.Remove(key);
                }
            }

            private struct CacheItem
            {
                public CacheItem(object item, int expiresMinutes)
                    : this()
                {
                    Item = item;
                    ExpireTime = DateTime.Now.AddMinutes(expiresMinutes);
                }

                public object Item { get; private set; }
                public DateTime ExpireTime { get; private set; }
            }
        }

}
2 голосов
/ 29 сентября 2011
// Consider this psuedo code for using Cache
public DataSet GetMySearchData(string search)
{
    // if it is in my cache already (notice search criteria is the cache key)
    string cacheKey = "Search " + search;
    if (Cache[cacheKey] != null)
    {
        return (DataSet)(Cache[cacheKey]);
    }
    else
    {
        DataSet result = yourDAL.DoSearch(search);
        Cache[cacheKey].Insert(result);  // There are more params needed here...
        return result;
    }
}

Ссылка: Как мне кэшировать набор данных, чтобы прекратить поездки в дБ?

1 голос
/ 29 сентября 2011

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CySoft.Collections
{
    public class Cache<TKey,TValue>
    {
        private readonly Dictionary<TKey, CacheItem> _cache = new Dictionary<TKey, CacheItem>();
        private TimeSpan _maxCachingTime;

        /// <summary>
        /// Creates a cache which holds the cached values for an infinite time.
        /// </summary>
        public Cache()
            : this(TimeSpan.MaxValue)
        {
        }

        /// <summary>
        /// Creates a cache which holds the cached values for a limited time only.
        /// </summary>
        /// <param name="maxCachingTime">Maximum time for which the a value is to be hold in the cache.</param>
        public Cache(TimeSpan maxCachingTime)
        {
            _maxCachingTime = maxCachingTime;
        }

        /// <summary>
        /// Tries to get a value from the cache. If the cache contains the value and the maximum caching time is
        /// not exceeded (if any is defined), then the cached value is returned, else a new value is created.
        /// </summary>
        /// <param name="key">Key of the value to get.</param>
        /// <param name="createValue">Function creating a new value.</param>
        /// <returns>A cached or a new value.</returns>
        public TValue Get(TKey key, Func<TValue> createValue)
        {
            CacheItem cacheItem;
            if (_cache.TryGetValue(key, out cacheItem) && (DateTime.Now - cacheItem.CacheTime) <= _maxCachingTime) {
                return cacheItem.Item;
            }
            TValue value = createValue();
            _cache[key] = new CacheItem(value);
            return value;
        }

        private struct CacheItem
        {
            public CacheItem(TValue item)
                : this()
            {
                Item = item;
                CacheTime = DateTime.Now;
            }

            public TValue Item { get; private set; }
            public DateTime CacheTime { get; private set; }
        }

    }
}

Вы можете передать лямбда-выражение в метод Get, который, например, извлекает значения из БД.

0 голосов
/ 29 сентября 2011

Вы можете просто использовать простой словарь.Что делает кэш таким особенным в веб-среде, так это то, что он сохраняется и имеет такую ​​область действия, что многие пользователи могут получить к нему доступ.В консольном приложении таких проблем нет.Если ваши потребности достаточно просты, словарь или аналогичные структуры можно использовать для быстрого поиска значений, которые вы извлекаете из базы данных.

0 голосов
/ 29 сентября 2011

Использовать шаблон синглтона.

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

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