Entity Framework MemoryCache TwoLevel Caching
| Ağustos 30, 20171 2 3 | Nuget PM> Install-Package EntityFramework 6.2 PM> Install-Package MemoryCache |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class MyDbConfiguration : DbConfiguration { /// <summary> /// InMemoryCache Nesnesi oluşturmayı sağlar. Entity Framework Query Cache için bir adet eklendi. /// Nuget Install-Package MemoryCache Ekli olması lazım. /// </summary> public static InMemoryCache EntityCache = new InMemoryCache(); public MyDbConfiguration() : base() { // Entity Framework Query Cache Eklenmesi sağlanyan kod. CacheTransactionHandler TransactionHandler = new CacheTransactionHandler(EntityCache); AddInterceptor(TransactionHandler); Loaded += (sender, args) => args.ReplaceService<DbProviderServices>((s, _) => new CachingProviderServices(s, TransactionHandler, new CachingPolicy())); // Entity Framework Query Cache Eklenmesi sağlanyan kod. } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | /// <summary> /// Entity Framework Query Cache hazır kodur. Entity SQL cümlelerini Cachelemeye yarar. /// https://github.com/moozzyk/EFCache or https://efcache.codeplex.com/releases/view/133097 /// </summary> public class InMemoryCache : ICache { private readonly Dictionary<string, CacheEntry> _cache = new Dictionary<string, CacheEntry>(); private readonly Dictionary<string, HashSet<string>> _entitySetToKey = new Dictionary<string, HashSet<string>>(); public bool GetItem(string key, out object value) { if (key == null) { throw new ArgumentNullException("key"); } value = null; lock (_cache) { var now = DateTimeOffset.Now; CacheEntry entry; if (_cache.TryGetValue(key, out entry)) { if (EntryExpired(entry, now)) { InvalidateItem(key); } else { entry.LastAccess = now; value = entry.Value; return true; } } } return false; } public void PutItem(string key, object value, IEnumerable<string> dependentEntitySets, TimeSpan slidingExpiration, DateTimeOffset absoluteExpiration) { if (key == null) { throw new ArgumentNullException("key"); } if (dependentEntitySets == null) { throw new ArgumentNullException("dependentEntitySets"); } lock (_cache) { var entitySets = dependentEntitySets.ToArray(); _cache[key] = new CacheEntry(value, entitySets, slidingExpiration, absoluteExpiration); foreach (var entitySet in entitySets) { HashSet<string> keys; if (!_entitySetToKey.TryGetValue(entitySet, out keys)) { keys = new HashSet<string>(); _entitySetToKey[entitySet] = keys; } keys.Add(key); } } } public void InvalidateSets(IEnumerable<string> entitySets) { if (entitySets == null) { throw new ArgumentNullException("entitySets"); } lock (_cache) { var itemsToInvalidate = new HashSet<string>(); foreach (var entitySet in entitySets) { HashSet<string> keys; if (_entitySetToKey.TryGetValue(entitySet, out keys)) { itemsToInvalidate.UnionWith(keys); _entitySetToKey.Remove(entitySet); } } foreach (var key in itemsToInvalidate) { InvalidateItem(key); } } } public void InvalidateItem(string key) { if (key == null) { throw new ArgumentNullException("key"); } lock (_cache) { CacheEntry entry; if (_cache.TryGetValue(key, out entry)) { _cache.Remove(key); foreach (var set in entry.EntitySets) { HashSet<string> keys; if (_entitySetToKey.TryGetValue(set, out keys)) { keys.Remove(key); } } } } } public void Purge() { lock (_cache) { var now = DateTimeOffset.Now; var itemsToRemove = new HashSet<string>(); foreach (var item in _cache) { if (EntryExpired(item.Value, now)) { itemsToRemove.Add(item.Key); } } foreach (var key in itemsToRemove) { InvalidateItem(key); } } } public int Count { get { return _cache.Count; } } private static bool EntryExpired(CacheEntry entry, DateTimeOffset now) { return entry.AbsoluteExpiration < now || (now - entry.LastAccess) > entry.SlidingExpiration; } private class CacheEntry { private readonly object _value; private readonly string[] _entitySets; private readonly TimeSpan _slidingExpiration; private readonly DateTimeOffset _absoluteExpiration; public CacheEntry(object value, string[] entitySets, TimeSpan slidingExpiration, DateTimeOffset absoluteExpiration) { _value = value; _entitySets = entitySets; _slidingExpiration = slidingExpiration; _absoluteExpiration = absoluteExpiration; LastAccess = DateTimeOffset.Now; } public object Value { get { return _value; } } public string[] EntitySets { get { return _entitySets; } } public TimeSpan SlidingExpiration { get { return _slidingExpiration; } } public DateTimeOffset AbsoluteExpiration { get { return _absoluteExpiration; } } public DateTimeOffset LastAccess { get; set; } } } |