EntityFrameworkCore.Cacheable icon indicating copy to clipboard operation
EntityFrameworkCore.Cacheable copied to clipboard

Cache Not "Flushing" and Going Back to Database

Open twurm opened this issue 5 years ago • 1 comments

Describe what is not working as expected.

The cache doesn't seem to be "flushing" and going back to the database when a record is added after the query is cached. An example test method is below to demonstrate.

Steps to reproduce

        /// <summary>
        /// Ensure that the cache is flushing correctly when new records are added.
        /// </summary>
        [TestMethod]
        public void CacheFlushingTest()
        {
            MemoryCacheProvider.ClearCache();

            var loggerProvider = new DebugLoggerProvider();
            var loggerFactory = new LoggerFactory(new[] { loggerProvider });

            var options = new DbContextOptionsBuilder<BloggingContext>()
                .UseLoggerFactory(loggerFactory)
                .UseInMemoryDatabase(databaseName: "EntityExpressionTest")
                .Options;

            // create test entries
            using (var initContext = new BloggingContext(options))
            {
                initContext.Blogs.Add(new Blog { BlogId = 1, Url = "http://sample.com/cats" });
                initContext.Blogs.Add(new Blog { BlogId = 2, Url = "http://sample.com/catfish" });
                initContext.SaveChanges();
            }

            using (var entityContext = new BloggingContext(options))
            {
                // shoud not hit cache, because first execution
                var result = entityContext.Blogs
                    .Where(d => d.BlogId > 1)
                    .Cacheable(TimeSpan.FromMinutes(5))
                    .ToList();

                // shoud hit cache, because second execution
                var cachedResult = entityContext.Blogs
                    .Where(d => d.BlogId > 1)
                    .Cacheable(TimeSpan.FromMinutes(5))
                    .ToList();

                Assert.AreEqual(result.Count, cachedResult.Count);
            }
            
            // create additional test entries
            using (var initContext = new BloggingContext(options))
            {
                initContext.Blogs.Add(new Blog { BlogId = 3, Url = "http://sample.com/dogs" });
                initContext.SaveChanges();
            }

            using (var entityContext = new BloggingContext(options))
            {
                // shoud not hit cache
                var result = entityContext.Blogs
                    .Where(d => d.BlogId > 1)
                    .Cacheable(TimeSpan.FromMinutes(5))
                    .ToList();

                // shoud hit cache, because second execution
                var cachedResult = entityContext.Blogs
                    .Where(d => d.BlogId > 1)
                    .Cacheable(TimeSpan.FromMinutes(5))
                    .ToList();

                Assert.AreEqual(2, cachedResult.Count);
            }

            // find "cache hit" log entries
            var logs = loggerProvider.Entries.Where(e => e.EventId == CacheableEventId.CacheHit);

            // cache should hit one time
            Assert.IsTrue(logs.Count() == 1);
        }

Further technical details

EntityFrameworkCore.Cacheable version: 2.0.0 EF Core version: 2.2.3 IDE: Visual Studio 2019.0

twurm avatar Apr 04 '19 12:04 twurm

@SteffenMangold any point to talk about it? I can analyze more deeply and understand what has been described here.

ralmsdeveloper avatar Jul 12 '19 02:07 ralmsdeveloper