public void TestInsertingDataIntoTheSameTableShouldInvalidateTheCacheAutomatically()
        {
            using (var context = new SampleContext())
            {
                var isActive = true;
                var name = "Product1";

                var databaseLog = new StringBuilder();
                context.Database.Log = commandLine =>
                {
                    databaseLog.AppendLine(commandLine);
                    Trace.Write(commandLine);
                };

                Trace.WriteLine("1st query, reading from db");
                var debugInfo1 = new EFCacheDebugInfo();
                var list1 = context.Products.Include(x => x.Tags)
                    .OrderBy(product => product.ProductNumber)
                    .Where(product => product.IsActive == isActive && product.ProductName == name)
                    .Cacheable(debugInfo1)
                    .ToList();
                var sqlCommands = databaseLog.ToString().Trim();
                Assert.AreEqual(false, string.IsNullOrWhiteSpace(sqlCommands));
                Assert.AreEqual(false, debugInfo1.IsCacheHit);
                Assert.IsTrue(list1.Any());


                Trace.WriteLine("same query, reading from 2nd level cache");
                databaseLog.Clear();
                var debugInfo2 = new EFCacheDebugInfo();
                var list2 = context.Products.Include(x => x.Tags)
                    .OrderBy(product => product.ProductNumber)
                    .Where(product => product.IsActive == isActive && product.ProductName == name)
                    .Cacheable(debugInfo2)
                    .ToList();
                sqlCommands = databaseLog.ToString().Trim();
                Assert.AreEqual(true, string.IsNullOrWhiteSpace(sqlCommands));
                Assert.AreEqual(true, debugInfo2.IsCacheHit);
                Assert.IsTrue(list2.Any());


                Trace.WriteLine("inserting data, invalidates the cache on SaveChanges");
                var rnd = new Random();
                var newProduct = new Product
                {
                    IsActive = false,
                    ProductName = "Product" + rnd.Next(),
                    ProductNumber = rnd.Next().ToString(),
                    Notes = "Notes ...",
                    UserId = 1
                };
                context.Products.Add(newProduct);
                context.SaveChanges();


                Trace.WriteLine("same query after insert, reading from database.");
                databaseLog.Clear();
                var debugInfo3 = new EFCacheDebugInfo();
                var list3 = context.Products.Include(x => x.Tags)
                    .OrderBy(product => product.ProductNumber)
                    .Where(product => product.IsActive == isActive && product.ProductName == name)
                    .Cacheable(debugInfo3)
                    .ToList();
                sqlCommands = databaseLog.ToString().Trim();
                Assert.AreEqual(false, string.IsNullOrWhiteSpace(sqlCommands));
                Assert.AreEqual(false, debugInfo3.IsCacheHit);
                Assert.IsTrue(list3.Any());
            }
        }
        public void TestTransactionRollbackShouldNotInvalidateTheCacheDependencyAutomatically()
        {
            using (var context = new SampleContext())
            {
                var isActive = true;
                var name = "Product1";

                var databaseLog = new StringBuilder();
                context.Database.Log = commandLine =>
                {
                    databaseLog.AppendLine(commandLine);
                    Trace.Write(commandLine);
                };

                Trace.WriteLine("1st query, reading from db.");
                var debugInfo1 = new EFCacheDebugInfo();
                var list1 = context.Products.Include(x => x.Tags)
                    .OrderBy(product => product.ProductNumber)
                    .Where(product => product.IsActive == isActive && product.ProductName == name)
                    .Cacheable(debugInfo1)
                    .ToList();
                var sqlCommands = databaseLog.ToString().Trim();
                Assert.AreEqual(false, string.IsNullOrWhiteSpace(sqlCommands));
                Assert.AreEqual(false, debugInfo1.IsCacheHit);
                Assert.IsTrue(list1.Any());


                Trace.WriteLine("same query, reading from 2nd level cache.");
                databaseLog.Clear();
                var debugInfo2 = new EFCacheDebugInfo();
                var list2 = context.Products.Include(x => x.Tags)
                    .OrderBy(product => product.ProductNumber)
                    .Where(product => product.IsActive == isActive && product.ProductName == name)
                    .Cacheable(debugInfo2)
                    .ToList();
                sqlCommands = databaseLog.ToString().Trim();
                Assert.AreEqual(true, string.IsNullOrWhiteSpace(sqlCommands));
                Assert.AreEqual(true, debugInfo2.IsCacheHit);
                Assert.IsTrue(list2.Any());

                Trace.WriteLine(
                    "inserting data with transaction.Rollback, shouldn't invalidate the cache on SaveChanges.");
                try
                {
                    var rnd = new Random();
                    var newProduct = new Product
                    {
                        IsActive = false,
                        ProductName = "Product1", // It has an `IsUnique` constraint.
                        ProductNumber = rnd.Next().ToString(),
                        Notes = "Notes ...",
                        UserId = 1
                    };
                    context.Products.Add(newProduct);
                    context.SaveChanges(); // it uses a transaction behind the scene.
                }
                catch (Exception ex)
                {
                    // ProductName is duplicate here and should throw an exception on save changes
                    // and rollback the transaction automatically.
                    Trace.WriteLine(ex.ToString());
                }

                Trace.WriteLine("same query after insert, reading from 2nd level cache.");
                databaseLog.Clear();
                var debugInfo3 = new EFCacheDebugInfo();
                var list3 = context.Products.Include(x => x.Tags)
                    .OrderBy(product => product.ProductNumber)
                    .Where(product => product.IsActive == isActive && product.ProductName == name)
                    .Cacheable(debugInfo3)
                    .ToList();
                sqlCommands = databaseLog.ToString().Trim();
                Assert.AreEqual(true, string.IsNullOrWhiteSpace(sqlCommands));
                Assert.AreEqual(true, debugInfo3.IsCacheHit);
                Assert.IsTrue(list3.Any());
            }
        }