diff --git a/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs b/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs index 85a7851e..0bb00fd8 100644 --- a/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs +++ b/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs @@ -39,43 +39,39 @@ public static bool TryGetValue(this IMemoryCache cache, object key, out T public static TItem Set(this IMemoryCache cache, object key, TItem value) { - using (var entry = cache.CreateEntry(key)) - { - entry.Value = value; - } + var entry = cache.CreateEntry(key); + entry.Value = value; + entry.Dispose(); return value; } public static TItem Set(this IMemoryCache cache, object key, TItem value, DateTimeOffset absoluteExpiration) { - using (var entry = cache.CreateEntry(key)) - { - entry.AbsoluteExpiration = absoluteExpiration; - entry.Value = value; - } + var entry = cache.CreateEntry(key); + entry.AbsoluteExpiration = absoluteExpiration; + entry.Value = value; + entry.Dispose(); return value; } public static TItem Set(this IMemoryCache cache, object key, TItem value, TimeSpan absoluteExpirationRelativeToNow) { - using (var entry = cache.CreateEntry(key)) - { - entry.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow; - entry.Value = value; - } + var entry = cache.CreateEntry(key); + entry.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow; + entry.Value = value; + entry.Dispose(); return value; } public static TItem Set(this IMemoryCache cache, object key, TItem value, IChangeToken expirationToken) { - using (var entry = cache.CreateEntry(key)) - { - entry.AddExpirationToken(expirationToken); - entry.Value = value; - } + var entry = cache.CreateEntry(key); + entry.AddExpirationToken(expirationToken); + entry.Value = value; + entry.Dispose(); return value; } @@ -100,11 +96,13 @@ public static TItem GetOrCreate(this IMemoryCache cache, object key, Func object result; if (!cache.TryGetValue(key, out result)) { - using (var entry = cache.CreateEntry(key)) - { - result = factory(entry); - entry.SetValue(result); - } + var entry = cache.CreateEntry(key); + result = factory(entry); + entry.SetValue(result); + // need to manually call dispose instead of having a using + // in case the factory passed in throws, in which case we + // do not want to add the entry to the cache + entry.Dispose(); } return (TItem)result; @@ -115,11 +113,13 @@ public static async Task GetOrCreateAsync(this IMemoryCache cache, object result; if (!cache.TryGetValue(key, out result)) { - using (var entry = cache.CreateEntry(key)) - { - result = await factory(entry); - entry.SetValue(result); - } + var entry = cache.CreateEntry(key); + result = await factory(entry); + entry.SetValue(result); + // need to manually call dispose instead of having a using + // in case the factory passed in throws, in which case we + // do not want to add the entry to the cache + entry.Dispose(); } return (TItem)result; diff --git a/test/Microsoft.Extensions.Caching.Memory.Tests/MemoryCacheSetAndRemoveTests.cs b/test/Microsoft.Extensions.Caching.Memory.Tests/MemoryCacheSetAndRemoveTests.cs index 1b269cf6..939ef1a2 100644 --- a/test/Microsoft.Extensions.Caching.Memory.Tests/MemoryCacheSetAndRemoveTests.cs +++ b/test/Microsoft.Extensions.Caching.Memory.Tests/MemoryCacheSetAndRemoveTests.cs @@ -167,6 +167,46 @@ public async Task GetOrCreateAsync_ReturnExistingValue() Assert.Same(obj, result); } + [Fact] + public void GetOrCreate_WillNotCreateEmptyValue_WhenFactoryThrows() + { + var cache = CreateCache(); + string key = "myKey"; + try + { + cache.GetOrCreate(key, entry => + { + throw new Exception(); + }); + } + catch (Exception) + { + } + + int obj; + Assert.False(cache.TryGetValue(key, out obj)); + } + + [Fact] + public async Task GetOrCreateAsync_WillNotCreateEmptyValue_WhenFactoryThrows() + { + var cache = CreateCache(); + string key = "myKey"; + try + { + await cache.GetOrCreateAsync(key, entry => + { + throw new Exception(); + }); + } + catch (Exception) + { + } + + int obj; + Assert.False(cache.TryGetValue(key, out obj)); + } + [Fact] public void SetOverwritesAndInvokesCallbacks() {