public void TestGetCacheDependenciesWorksForInserts() { const string commandText = @"SET NOCOUNT ON; INSERT INTO [Products] ([IsActive], [Notes], [ProductName], [ProductNumber], [UserId]) VALUES (@p0, @p1, @p2, @p3, @p4); SELECT [ProductId] FROM [Products] WHERE @@ROWCOUNT = 1 AND [ProductId] = scope_identity();"; var cacheDependenciesProcessor = EFServiceProvider.GetRequiredService <IEFCacheDependenciesProcessor>(); var cacheDependencies = cacheDependenciesProcessor.GetCacheDependencies(new EFCachePolicy(), new SortedSet <string> { "Posts", "Users", "Products" }, commandText); var inUseTableNames = new SortedSet <string> { CacheKeyPrefix + "Products" }; CollectionAssert.AreEqual(expected: inUseTableNames, actual: cacheDependencies); }
public void TestGetCacheDependenciesWorks() { const string commandText = @"-- EFCachePolicy[Index(27)] --> Absolute|00:45:00 SELECT TOP(1) [p].[Id], [p].[Title], [p].[UserId], [p].[post_type], [u].[Id], [u].[Name], [u].[UserStatus] FROM [Posts] AS [p] INNER JOIN [Users] AS [u] ON [p].[UserId] = [u].[Id] WHERE [p].[post_type] IN (N'post_base', N'post_page') AND ([p].[Id] > @__param1_0) ORDER BY [p].[Id]"; var cacheDependenciesProcessor = EFServiceProvider.GetRequiredService <IEFCacheDependenciesProcessor>(); var cacheDependencies = cacheDependenciesProcessor.GetCacheDependencies(new EFCachePolicy(), new SortedSet <string> { "Posts", "Users", "Products" }, commandText); var inUseTableNames = new SortedSet <string> { "Posts", "Users" }; CollectionAssert.AreEqual(expected: inUseTableNames, actual: cacheDependencies); }
public virtual void TestInsertingNullValues(TestCacheProvider cacheProvider) { var cacheService = EFServiceProvider.GetCacheServiceProvider(cacheProvider); var efCachePolicy = new EFCachePolicy().Timeout(TimeSpan.FromMinutes(10)).ExpirationMode(CacheExpirationMode.Absolute); var key1 = new EFCacheKey { KeyHash = "EF_key1", CacheDependencies = new HashSet <string> { "entity1", "entity2" } }; cacheService.InsertValue( key1, null, efCachePolicy); var value1 = cacheService.GetValue(key1, efCachePolicy); Assert.IsTrue(value1.IsNull, $"value1 is `{value1}`"); }
public async Task TestCacheableWorksWithSPs(bool useRedis) { await EFServiceProvider.RunInContextAsync(useRedis, LogLevel.Information, false, async (context, loggerProvider) => { var blogId = 1; var blogs = await context.Set <BlogData>() .FromSqlRaw("usp_GetBlogData {0}", blogId) .Cacheable() .ToListAsync(); Assert.IsTrue(blogs.Any()); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); blogs = await context.Set <BlogData>() .FromSqlRaw("usp_GetBlogData {0}", blogId) .Cacheable() .ToListAsync(); Assert.IsTrue(blogs.Any()); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); }); }
public void TestGetEFCachePolicyWithAllParts() { string commandText = EFCachePolicy.Configure(options => options.ExpirationMode(CacheExpirationMode.Absolute) .Timeout(TimeSpan.FromMinutes(45)) .SaltKey("saltKey") .CallerMemberName("methodName") .CallerLineNumber(10) .CacheDependencies("item 1", "item 2")); var cachePolicyParser = EFServiceProvider.GetRequiredService <IEFCachePolicyParser>(); var cachePolicy = cachePolicyParser.GetEFCachePolicy(commandText); Assert.AreEqual(expected: CacheExpirationMode.Absolute, actual: cachePolicy.CacheExpirationMode); Assert.AreEqual(expected: TimeSpan.FromMinutes(45), actual: cachePolicy.CacheTimeout); Assert.AreEqual(expected: "saltKey", actual: cachePolicy.CacheSaltKey); CollectionAssert.AreEqual(expected: new SortedSet <string> { "item 1", "item 2" }, actual: cachePolicy.CacheItemsDependencies as SortedSet <string>); }
public void TestGetEFCachePolicyWithAdditionalTagComments() { const string commandText = @"-- CustomTagAbove -- EFCachePolicy[Index(27)] --> Absolute|00:45:00 -- CustomTagBelow SELECT TOP(1) [p].[Id], [p].[Title], [p].[UserId], [p].[post_type], [u].[Id], [u].[Name], [u].[UserStatus] FROM [Posts] AS [p] INNER JOIN [Users] AS [u] ON [p].[UserId] = [u].[Id] WHERE [p].[post_type] IN (N'post_base', N'post_page') AND ([p].[Id] > @__param1_0) ORDER BY [p].[Id]"; var cachePolicyParser = EFServiceProvider.GetRequiredService <IEFCachePolicyParser>(); var cachePolicy = cachePolicyParser.GetEFCachePolicy(commandText); Assert.AreEqual(expected: CacheExpirationMode.Absolute, actual: cachePolicy.CacheExpirationMode); Assert.AreEqual(expected: TimeSpan.FromMinutes(45), actual: cachePolicy.CacheTimeout); }
public void TestNullValuesWillUseTheCache(TestCacheProvider cacheProvider) { EFServiceProvider.RunInContext(cacheProvider, LogLevel.Debug, false, (context, loggerProvider) => { var item1 = context.Products .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive && product.ProductName == "Product1xx") .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNull(item1); var item2 = context.Products .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive && product.ProductName == "Product1xx") .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsNull(item2); }); }
public void TestInsertingDataToRelatedTablesShouldInvalidateTheCacheDependencyAutomatically(TestCacheProvider cacheProvider) { EFServiceProvider.RunInContext(cacheProvider, LogLevel.Debug, false, (context, loggerProvider) => { var isActive = true; var name = "Product1"; var list1 = context.Products.Include(x => x.TagProducts).ThenInclude(x => x.Tag) .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsTrue(list1.Any()); var list2 = context.Products.Include(x => x.TagProducts).ThenInclude(x => x.Tag) .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsTrue(list2.Any()); var tag = new Tag { Name = $"Tag {RandomNumberProvider.Next()}" }; context.Tags.Add(tag); context.SaveChanges(); var list3 = context.Products.Include(x => x.TagProducts).ThenInclude(x => x.Tag) .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsTrue(list3.Any()); }); }
public void TestInsertingDataToOtherTablesShouldNotInvalidateTheCacheDependencyAutomatically(bool useRedis) { EFServiceProvider.RunInContext(useRedis, LogLevel.Information, false, (context, loggerProvider) => { var isActive = true; var name = "Product4"; var list1 = context.Products.Include(x => x.TagProducts).ThenInclude(x => x.Tag) .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsTrue(!list1.Any()); var list2 = context.Products.Include(x => x.TagProducts).ThenInclude(x => x.Tag) .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsTrue(!list2.Any()); var user = new User { Name = $"User {RandomNumberProvider.Next()}" }; context.Users.Add(user); context.SaveChanges(); var list3 = context.Products.Include(x => x.TagProducts).ThenInclude(x => x.Tag) .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsTrue(!list3.Any()); }); }
public void TestAllDateTypes(TestCacheProvider cacheProvider) { EFServiceProvider.RunInContext(cacheProvider, LogLevel.Debug, false, (context, loggerProvider) => { var items1 = context.DateTypes .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(items1); Assert.IsTrue(items1.First().UpdateDate.Millisecond > 0); var items2 = context.DateTypes .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(items2); Assert.IsTrue(items2.First().UpdateDate.Millisecond > 0); }); }
public async Task TestCacheInvalidationWorksWithSPs(bool useRedis) { await EFServiceProvider.RunInContextAsync(useRedis, LogLevel.Information, false, async (context, loggerProvider) => { var blogId = 1; var blogs = await context.Set <BlogData>() .FromSqlRaw("usp_GetBlogData {0}", blogId) .Cacheable() .ToListAsync(); Assert.IsTrue(blogs.Any()); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); blogs = await context.Set <BlogData>() .FromSqlRaw("usp_GetBlogData {0}", blogId) .Cacheable() .ToListAsync(); Assert.IsTrue(blogs.Any()); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); var product = new Product { IsActive = false, ProductName = $"Product{RandomNumberProvider.Next()}", ProductNumber = RandomNumberProvider.Next().ToString(), Notes = "Notes ...", UserId = 1 }; context.Products.Add(product); await context.SaveChangesAsync(); blogs = await context.Set <BlogData>() .FromSqlRaw("usp_GetBlogData {0}", blogId) .Cacheable() .ToListAsync(); Assert.IsTrue(blogs.Any()); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); }); }
public void TestCachingByteArrays(TestCacheProvider cacheProvider) { EFServiceProvider.RunInContext(cacheProvider, LogLevel.Debug, false, (context, loggerProvider) => { User user1; const string user1Name = "User1"; var binaryData = new byte[] { 1, 2, 3 }; if (!context.Users.Any(user => user.Name == user1Name)) { user1 = new User { Name = user1Name, ImageData = binaryData }; user1 = context.Users.Add(user1).Entity; } else { user1 = context.Users.First(user => user.Name == user1Name); user1.ImageData = binaryData; } context.SaveChanges(); var userData = context.Users .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(p => p.Id == user1.Id); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(userData); CollectionAssert.AreEqual(binaryData, userData.ImageData); userData = context.Users .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(p => p.Id == user1.Id); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(userData); CollectionAssert.AreEqual(binaryData, userData.ImageData); }); }
public async Task TestCacheAllQueriesWorks(TestCacheProvider cacheProvider) { await EFServiceProvider.RunInContextAsync(cacheProvider, LogLevel.Debug, true, async (context, loggerProvider) => { var isActive = true; var name = "Product1"; var list1 = await context.Products .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .ToListAsync(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsTrue(list1.Any()); var list2 = await context.Products .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .ToListAsync(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsTrue(list2.Any()); }); }
public void PerformanceTest(bool useRedis) { const decimal loopCount = 1000; EFServiceProvider.RunInContext(useRedis, LogLevel.Warning, false, (context, debugLoggerProvider) => { Stopwatch watch = new Stopwatch(); watch.Start(); // run normal queries for (int i = 0; i < loopCount; i++) { var result = context.Posts.Where(post => post.Id >= 0).Take(100).ToList(); } var uncachedTimeSpan = watch.Elapsed; // cache the query result var posts = context.Posts.Where(post => post.Id >= 0).Take(100).Cacheable().ToList(); watch.Restart(); // run cached queries for (int i = 0; i < loopCount; i++) { var result = context.Posts.Where(post => post.Id >= 0).Take(100).Cacheable().ToList(); } var cachedTimeSpan = watch.Elapsed; var message = $"Average database query duration [+{TimeSpan.FromTicks((long)(uncachedTimeSpan.Ticks / loopCount))}].\n" + $"Average cache query duration [+{TimeSpan.FromTicks((long)(cachedTimeSpan.Ticks / loopCount))}].\n" + $"Cached queries are x{(uncachedTimeSpan.Ticks / (decimal)cachedTimeSpan.Ticks) - 1:N2} times faster."; Assert.IsTrue(uncachedTimeSpan > cachedTimeSpan, message); }); }
public void TestRemoveDataShouldInvalidateTheCacheAutomatically(TestCacheProvider cacheProvider) { EFServiceProvider.RunInContext(cacheProvider, LogLevel.Debug, false, (context, loggerProvider) => { var isActive = false; var name = "Product4"; var list1 = context.Products.Include(x => x.TagProducts).ThenInclude(x => x.Tag) .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(list1); var list2 = context.Products.Include(x => x.TagProducts).ThenInclude(x => x.Tag) .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsTrue(list2.Any()); var product1 = context.Products.First(product => product.ProductName == name); product1.Notes = $"Test ... {RandomNumberProvider.Next()}"; context.SaveChanges(); var list3 = context.Products.Include(x => x.TagProducts).ThenInclude(x => x.Tag) .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .ToList(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(list3); }); }
public void Test2DifferentCollectionsWillNotUseTheCache(TestCacheProvider cacheProvider) { EFServiceProvider.RunInContext(cacheProvider, LogLevel.Debug, false, (context, loggerProvider) => { var collection1 = new[] { 1, 2, 3 }; var item1 = context.Products .Where(product => collection1.Contains(product.ProductId)) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(item1); var collection2 = new[] { 1, 2, 3, 4 }; var item2 = context.Products .Where(product => collection2.Contains(product.ProductId)) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(item2); }); }
public void TestSecondLevelCacheUsingTwoCountMethods(TestCacheProvider cacheProvider) { EFServiceProvider.RunInContext(cacheProvider, LogLevel.Debug, false, (context, loggerProvider) => { var isActive = true; var name = "Product3"; var count = context.Products .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .Count(); Assert.AreEqual(0, loggerProvider.GetCacheHitCount(), $"cacheProvider: {cacheProvider}"); Assert.IsTrue(count > 0); count = context.Products .OrderBy(product => product.ProductNumber) .Where(product => product.IsActive == isActive && product.ProductName == name) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .Count(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsTrue(count > 0); }); }
public void TestQueriesUsingExplicitTransactionsWillInvalidateTheCache(TestCacheProvider cacheProvider) { var rnd = new Random(); EFServiceProvider.RunInContext(cacheProvider, LogLevel.Debug, false, (context, loggerProvider) => { // Read and cache data var entity0 = context.Tags.Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)).First(); using (var txn = context.Database.BeginTransaction()) { // Read and modify an entity. var entity1 = context.Tags.Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)).First(); // Reading the data from the database, not cache. Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); entity1.Name = $"FOO{rnd.Next()}"; // Save the change, cache will be invalidated. context.SaveChanges(); // Read the same entity again. entity1 = context.Tags.Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)).First(); // Reading the data from the database, not cache. Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); context.SaveChanges(); txn.Commit(); } // `After` committing the transaction, the related query cache should be invalidated. var entity2 = context.Tags.Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)).First(); // Reading the data from the database after invalidation, not cache. Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); }); }
public void TestAddThenRemoveDataShouldInvalidateTheCacheAutomatically(bool useRedis) { EFServiceProvider.RunInContext(useRedis, LogLevel.Information, false, (context, loggerProvider) => { User user1; const string user1Name = "User1"; if (!context.Users.Any(user => user.Name == user1Name)) { user1 = new User { Name = user1Name }; user1 = context.Users.Add(user1).Entity; } else { user1 = context.Users.First(user => user.Name == user1Name); } var product = new Product { IsActive = false, ProductName = $"Product{RandomNumberProvider.Next()}", ProductNumber = RandomNumberProvider.Next().ToString(), Notes = "Notes ...", UserId = 1 }; context.Products.Add(product); context.SaveChanges(); var p98 = context.Products .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(p => p.ProductId == product.ProductId); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(p98); var firstQueryWithWhereClauseResult = context.Products.Where(p => p.ProductId == product.ProductId) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(firstQueryWithWhereClauseResult); context.Products.Remove(product); context.SaveChanges(); p98 = context.Products .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(p => p.ProductId == product.ProductId); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNull(p98); var firstQueryWithWhereClauseResult2 = context.Products.Where(p => p.ProductId == product.ProductId) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsNull(firstQueryWithWhereClauseResult2); p98 = context.Products.FirstOrDefault(p => p.ProductId == product.ProductId); Assert.IsNull(p98); }); }
private static void clearAllCachedEntries() { EFServiceProvider.GetRedisCacheServiceProvider().ClearAllCachedEntries(); }
private static void clearAllCachedEntries() { EFServiceProvider.GetCacheServiceProvider(TestCacheProvider.CacheManagerCoreRedis).ClearAllCachedEntries(); }
protected virtual IEFCacheServiceProvider GetCacheServiceProvider(bool useRedis) { return(useRedis ? EFServiceProvider.GetInMemoryCacheServiceProvider() : EFServiceProvider.GetRedisCacheServiceProvider()); }
public void TestAddThenRemoveDataShouldInvalidateTheCacheAutomatically(TestCacheProvider cacheProvider) { EFServiceProvider.RunInContext(cacheProvider, LogLevel.Debug, false, (context, loggerProvider) => { User user1; const string user1Name = "User1"; if (!context.Users.Any(user => user.Name == user1Name)) { user1 = new User { Name = user1Name, AddDate = new DateTime(2020, 4, 3, 17, 50, 39, 503), UpdateDate = null, Points = 1000, IsActive = true, ByteValue = 1, CharValue = 'C', DateTimeOffsetValue = new DateTimeOffset(new DateTime(2020, 4, 3, 17, 50, 39, 503)), DecimalValue = 1.1M, DoubleValue = 1.3, FloatValue = 1.2f, GuidValue = new Guid("236bbe40-b861-433c-8789-b152a99cfe3e"), TimeSpanValue = new TimeSpan(1, 0, 0, 0, 0), ShortValue = 2, ByteArrayValue = new byte[] { 1, 2 }, UintValue = 1, UlongValue = 1, UshortValue = 1 }; user1 = context.Users.Add(user1).Entity; } else { user1 = context.Users.First(user => user.Name == user1Name); } var userOne = context.Users.Cacheable().First(user => user.Name == user1Name); userOne = context.Users.Cacheable().First(user => user.Name == user1Name); Assert.IsNotNull(userOne); loggerProvider.ClearItems(); var product = new Product { IsActive = false, ProductName = $"Product{RandomNumberProvider.Next()}", ProductNumber = RandomNumberProvider.Next().ToString(), Notes = "Notes ...", UserId = 1 }; context.Products.Add(product); context.SaveChanges(); var p98 = context.Products .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(p => p.ProductId == product.ProductId); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(p98); var firstQueryWithWhereClauseResult = context.Products.Where(p => p.ProductId == product.ProductId) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsNotNull(firstQueryWithWhereClauseResult); context.Products.Remove(product); context.SaveChanges(); p98 = context.Products .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(p => p.ProductId == product.ProductId); Assert.AreEqual(0, loggerProvider.GetCacheHitCount()); Assert.IsNull(p98); var firstQueryWithWhereClauseResult2 = context.Products.Where(p => p.ProductId == product.ProductId) .Cacheable(CacheExpirationMode.Absolute, TimeSpan.FromMinutes(45)) .FirstOrDefault(); Assert.AreEqual(1, loggerProvider.GetCacheHitCount()); Assert.IsNull(firstQueryWithWhereClauseResult2); p98 = context.Products.FirstOrDefault(p => p.ProductId == product.ProductId); Assert.IsNull(p98); }); }