Inheritance: System.Net.Http.Headers.EntityTagHeaderValue
コード例 #1
0
        // TODO: !!! routePattern implementation needs to be changed to Cas
        public void AddOrUpdate(CacheKey key, TimedEntityTagHeaderValue eTag)
        {
            // add item
            _memcachedClient.ExecuteStore(StoreMode.Set, key.HashBase64, eTag.ToString());

            // add route pattern if not there
            string keyForRoutePattern = GetKeyForRoutePattern(key.RoutePattern);
            string keyForResourceUri = GetKeyForResourceUri(key.ResourceUri);
            var routePatternEntries = GetRoutePatternEntries(key.RoutePattern);
            var resourceUriEntries = GetResourceUriEntries(key.ResourceUri);

            if (!routePatternEntries.Contains(key.HashBase64))
            {
                var bytes = new List<byte>();
                foreach (var routePatternEntry in routePatternEntries)
                {
                    bytes.AddRange(new LengthedPrefixedString(routePatternEntry).ToByteArray());
                }
                bytes.AddRange(new LengthedPrefixedString(key.HashBase64).ToByteArray());
                _memcachedClient.ExecuteStore(StoreMode.Set, keyForRoutePattern, bytes.ToArray());

            }

            if (!resourceUriEntries.Contains(key.HashBase64))
            {
                var bytes = new List<byte>();
                foreach (var routePatternEntry in resourceUriEntries)
                {
                    bytes.AddRange(new LengthedPrefixedString(routePatternEntry).ToByteArray());
                }
                bytes.AddRange(new LengthedPrefixedString(key.HashBase64).ToByteArray());
                _memcachedClient.ExecuteStore(StoreMode.Set, keyForResourceUri, bytes.ToArray());

            }
        }
コード例 #2
0
        public void AddOrUpdate(CacheKey key, TimedEntityTagHeaderValue eTag)
        {
            TimedEntityTagHeaderValue test;
            if (!TryGetValue(key, out test))
            {
                var cacheKey = new PersistentCacheKey
                {
                    Hash = key.Hash,
                    RoutePattern = key.RoutePattern,
                    ETag = eTag.Tag,
                    LastModified = eTag.LastModified
                };

                using (var connection = new MongoEntiryStoreConnection(this.connectionString))
                {
                    connection.DocumentStore.Save(cacheKey);
                }
            }
            else
            {
                using (var connection = new MongoEntiryStoreConnection(this.connectionString))
                {
                    var cacheKey = connection.DocumentStore.AsQueryable().FirstOrDefault(x => x.Hash == key.Hash);
                    if (cacheKey != null)
                    {
                        cacheKey.ETag = eTag.Tag;
                        cacheKey.LastModified = eTag.LastModified;
                        connection.DocumentStore.Save(cacheKey);
                    }
                }
            }
        }
コード例 #3
0
        public static bool TryParse(string timedETagValue, out TimedEntityTagHeaderValue value)
        {
            value = null;
            if (timedETagValue == null)
            {
                return(false);
            }

            var strings = timedETagValue.Split(new[] { "\r\n" }, StringSplitOptions.None);

            if (strings.Length != 2)
            {
                return(false);
            }

            EntityTagHeaderValue etag = null;
            DateTimeOffset       lastModified;

            if (!TryParse(strings[0], out etag))
            {
                return(false);
            }

            if (!DateTimeOffset.TryParse(strings[1], out lastModified))
            {
                return(false);
            }

            value = new TimedEntityTagHeaderValue(etag.Tag, etag.IsWeak)
            {
                LastModified = lastModified
            };
            return(true);
        }
コード例 #4
0
        public void AddTest()
        {
            var cacheKey = new CacheKey("/api/Cars", new[] { "1234", "abcdef" });
            var documentStore = new EmbeddableDocumentStore()
            {
                RunInMemory = true
            }.Initialize();

            new RavenDocumentsByEntityName().Execute(documentStore);

            var store = new RavenDbEntityTagStore(documentStore);
            var value = new TimedEntityTagHeaderValue("\"abcdef1234\"") { LastModified = DateTime.Now };

            // first remove them
            store.RemoveAllByRoutePattern(cacheKey.RoutePattern);

            // add
            store.AddOrUpdate(cacheKey, value);

            // get
            TimedEntityTagHeaderValue dbValue;
            store.TryGetValue(cacheKey, out dbValue);

            Assert.AreEqual(value.Tag, dbValue.Tag);
            Assert.AreEqual(value.LastModified.ToString(), dbValue.LastModified.ToString());
        }
コード例 #5
0
        public static void GetMatchNonMatchTest(
			string headerName, 
			string[] values, 
			bool existsInStore,
			bool expectReturnNull,
			HttpStatusCode expectedStatus = HttpStatusCode.Unused)
        {
            // setup
            var mocks = new MockRepository();
            var entityTagStore = mocks.StrictMock<IEntityTagStore>();
            var entityTagHandler = new CachingHandler(entityTagStore);
            var request = new HttpRequestMessage(HttpMethod.Get, TestUrl);
            request.Headers.Add(headerName, values);
            TimedEntityTagHeaderValue entityTagHeaderValue = new TimedEntityTagHeaderValue("\"12345678\"");

            if(values.Length>0) // if
                entityTagStore.Expect(x => x.TryGetValue(Arg<CacheKey>.Matches(etg => etg.ResourceUri == entityTagHandler.UriTrimmer(new Uri(TestUrl))),
                    out Arg<TimedEntityTagHeaderValue>.Out(entityTagHeaderValue).Dummy)).Return(existsInStore);

            mocks.ReplayAll();

            // run
            var matchNoneMatch = entityTagHandler.GetIfMatchNoneMatch();
            // verify
            Task<HttpResponseMessage> resultTask = matchNoneMatch(request);
            Assert.That(expectReturnNull ^ resultTask != null, "result was not as expected");
            if(resultTask!=null && expectedStatus != HttpStatusCode.Unused)
            {
                Assert.AreEqual(expectedStatus, resultTask.Result.StatusCode, "Status code");
            }
            mocks.VerifyAll();
        }
コード例 #6
0
        public void AddOrUpdate(CacheKey key, TimedEntityTagHeaderValue eTag)
        {
            TimedEntityTagHeaderValue test;
            if (!TryGetValue(key, out test))
            {
                var cacheKey = new PersistentCacheKey
                {
                    Hash = key.Hash,
                    RoutePattern = key.RoutePattern,
                    CustomEtag = eTag.Tag,
                    LastModified = eTag.LastModified,
                    ResourceUri = key.ResourceUri
                };

                _session.Store(cacheKey);
            }
            else
            {
                var cacheKey = _session.Query<PersistentCacheKey>()
                    .Customize(x => x.WaitForNonStaleResults())
                    .FirstOrDefault(x => x.Hash == key.Hash);

                cacheKey.CustomEtag = eTag.Tag;
                cacheKey.LastModified = eTag.LastModified;
                cacheKey.ResourceUri = key.ResourceUri;
                cacheKey.RoutePattern = key.RoutePattern;
                _session.Store(cacheKey);
            }
        }
コード例 #7
0
        public void AddOrUpdate(CacheKey key, TimedEntityTagHeaderValue eTag)
        {
            TimedEntityTagHeaderValue test;
            if (!TryGetValue(key, out test))
            {
                var cacheKey = new PersistentCacheKey()
                {
                    Hash = key.Hash,
                    RoutePattern = key.RoutePattern,
                    ETag = eTag.Tag,
                    LastModified = eTag.LastModified
                };
                using (var session = _documentStore.OpenSession())
                {
                    session.Store(cacheKey);
                    session.SaveChanges();
                }

            }
            else
            {
                using (var session = _documentStore.OpenSession())
                {
                    var cacheKey =
                        session.Query<PersistentCacheKey>()
                        .Customize(x => x.WaitForNonStaleResults())
                        .FirstOrDefault(x => x.Hash == key.Hash);
                    cacheKey.ETag = eTag.Tag;
                    cacheKey.LastModified = eTag.LastModified;
                    session.Store(cacheKey);
                    session.SaveChanges();
                }
            }
        }
コード例 #8
0
ファイル: IntegrationTests.cs プロジェクト: yyf919/CacheCow
		public void UpdateTest()
		{
			var cacheKey = new CacheKey("/api/Cars", new[] { "1234", "abcdef" });
			var store = new SqlServerEntityTagStore();
			var value = new TimedEntityTagHeaderValue("\"abcdef1234\"") { LastModified = DateTime.Now };


			// first remove them
			store.RemoveAllByRoutePattern(cacheKey.RoutePattern);

			// add
			store.AddOrUpdate(cacheKey, value);

			// get
			TimedEntityTagHeaderValue dbValue;
			store.TryGetValue(cacheKey, out dbValue);

			value.LastModified = DateTime.Now.AddDays(-1);

			// update
			store.AddOrUpdate(cacheKey, value);

			// get
			TimedEntityTagHeaderValue dbValue2;
			store.TryGetValue(cacheKey, out dbValue2);

			Assert.AreEqual(dbValue.Tag, dbValue2.Tag);
			Assert.Greater(dbValue.LastModified, dbValue2.LastModified);
			Console.WriteLine(dbValue2.Tag);
			Console.WriteLine(dbValue2.LastModified);
		}
コード例 #9
0
		public static bool TryParse(string timedETagValue, out TimedEntityTagHeaderValue value)
		{
			value = null;
			if (timedETagValue == null)
				return false;

			var strings = timedETagValue.Split(new[] { "\r\n" }, StringSplitOptions.None);
			if (strings.Length != 2)
				return false;

			EntityTagHeaderValue etag = null;
			DateTimeOffset lastModified;
			if (!EntityTagHeaderValue.TryParse(strings[0], out etag))
				return false;

			if (!DateTimeOffset.TryParse(strings[1], out lastModified))
				return false;

			value = new TimedEntityTagHeaderValue(etag.Tag, etag.IsWeak)
			{
				LastModified = lastModified
			};
			return true;

		}
コード例 #10
0
		public bool TryGetValue(CacheKey key, out TimedEntityTagHeaderValue eTag)
		{
			eTag = null;
			using (var connection = new SqlConnection(this._connectionString))
			using (var command = new SqlCommand())
			{
				connection.Open();
				command.Connection = connection;
				command.CommandText = this.GetStoredProcedureName(StoredProcedureNames.GetCache);
				command.CommandType = CommandType.StoredProcedure;
				command.Parameters.AddWithValue(ColumnNames.CacheKeyHash, key.Hash);

				using (var reader = command.ExecuteReader( CommandBehavior.CloseConnection))
				{
					if(!reader.HasRows)
						return false;

					reader.Read(); // there must be only one record

					eTag= new TimedEntityTagHeaderValue((string) reader[ColumnNames.ETag])
					      	{
					      		LastModified = DateTime.SpecifyKind((DateTime)reader[ColumnNames.LastModified], DateTimeKind.Utc)
					      	};
					return true;
				}
			}
		}
コード例 #11
0
ファイル: CachingHandlerTests.cs プロジェクト: sh54/CacheCow
        public static void AddCaching(string method,
			bool existsInStore,
			bool addVaryHeader,
			bool addLastModifiedHeader,
			bool alreadyHasLastModified,
			string[] varyByHeader)
        {
            // setup
            var mocks = new MockRepository();
            var request = new HttpRequestMessage(new HttpMethod(method), TestUrl);
            request.Headers.Add(HttpHeaderNames.Accept, "text/xml");
            request.Headers.Add(HttpHeaderNames.AcceptLanguage, "en-GB");
            var entityTagStore = mocks.StrictMock<IEntityTagStore>();
            var entityTagHeaderValue = new TimedEntityTagHeaderValue("\"12345678\"");
            var cachingHandler = new CachingHandler(entityTagStore, varyByHeader)
            {
                AddLastModifiedHeader = addLastModifiedHeader,
                AddVaryHeader = addVaryHeader,
                ETagValueGenerator = (x,y) => entityTagHeaderValue
            };

            var entityTagKey = new CacheKey(TestUrl, new[] {"text/xml", "en-GB"}, TestUrl + "/*");

            entityTagStore.Expect(x => x.TryGetValue(Arg<CacheKey>.Matches(etg => etg.ResourceUri == TestUrl),
                out Arg<TimedEntityTagHeaderValue>.Out(entityTagHeaderValue).Dummy)).Return(existsInStore);

            if (!existsInStore)
            {
                entityTagStore.Expect(
                    x => x.AddOrUpdate(Arg<CacheKey>.Matches(etk => etk == entityTagKey),
                        Arg<TimedEntityTagHeaderValue>.Matches(ethv => ethv.Tag == entityTagHeaderValue.Tag)));
            }

            var response = new HttpResponseMessage();
            response.Content = new ByteArrayContent(new byte[0]);
            if (alreadyHasLastModified)
                response.Content.Headers.Add(HttpHeaderNames.LastModified, DateTimeOffset.Now.ToString("r"));

            var cachingContinuation = cachingHandler.AddCaching(entityTagKey, request, response, request.Headers);
            mocks.ReplayAll();

            // run
            cachingContinuation();

            // verify

            // test kast modified only if it is GET and PUT
            if (addLastModifiedHeader && method.IsIn("PUT", "GET"))
            {
                Assert.That(response.Content.Headers.Any(x => x.Key == HttpHeaderNames.LastModified),
                    "LastModified does not exist");
            }
            if (!addLastModifiedHeader && !alreadyHasLastModified)
            {
                Assert.That(!response.Content.Headers.Any(x => x.Key == HttpHeaderNames.LastModified),
                    "LastModified exists");
            }
            mocks.VerifyAll();
        }
コード例 #12
0
 public void AddOrUpdate(CacheKey key, TimedEntityTagHeaderValue eTag)
 {
     cache.Put(key.HashBase64, eTag.ToString(), new[]
                                        {
                                            new DataCacheTag(key.ResourceUri),
                                            new DataCacheTag(key.RoutePattern),
                                        }, CacheRegion);
 }
コード例 #13
0
		public bool TryGetValue(CacheKey key, out TimedEntityTagHeaderValue eTag)
		{
            var cacheObject = _cache.Get(key.HashBase64, _regionName) as string;

			if (!TimedEntityTagHeaderValue.TryParse(cacheObject, out eTag))
				return false;

			return true;
		}
コード例 #14
0
 public void AddOrUpdate(CacheKey key, TimedEntityTagHeaderValue eTag)
 {
     _eTagCache.AddOrUpdate(key, eTag, (theKey, oldValue) => eTag);
     _routePatternCache.AddOrUpdate(key.RoutePattern, new HashSet<CacheKey>() { key },
         (routePattern, hashSet) =>
         {
             hashSet.Add(key);
             return hashSet;
         });
 }
コード例 #15
0
		public static void ToStringAndTryParseTest(string tag, bool isWeak)
		{
			var headerValue = new TimedEntityTagHeaderValue(tag, isWeak);
			var s = headerValue.ToString();
			TimedEntityTagHeaderValue headerValue2 = null;
			Assert.IsTrue(TimedEntityTagHeaderValue.TryParse(s, out headerValue2));
			Assert.AreEqual(headerValue.Tag, headerValue2.Tag);
			Assert.AreEqual(headerValue.LastModified.ToString(), headerValue2.LastModified.ToString());
			Assert.AreEqual(headerValue.IsWeak, headerValue2.IsWeak);
			Assert.AreEqual(headerValue.ToString(), headerValue2.ToString());
		}
コード例 #16
0
        public bool TryGetValue(CacheKey key, out TimedEntityTagHeaderValue eTag)
        {
            eTag = null;
            string value = _database.StringGet(key.HashBase64);
            if (!string.IsNullOrEmpty(value))
            {
                return TimedEntityTagHeaderValue.TryParse(value, out eTag);
            }

            return false;
        }
コード例 #17
0
 public void AddRemoveTest()
 {
     using (var store = new InMemoryEntityTagStore())
     {
         var cacheKey = new CacheKey(Url, new[] { "Accept" });
         var headerValue = new TimedEntityTagHeaderValue("\"abcdefghijkl\"");
         store.AddOrUpdate(cacheKey, headerValue);
         store.TryRemove(cacheKey);
         TimedEntityTagHeaderValue storedHeader;
         Assert.False(store.TryGetValue(cacheKey, out storedHeader));
         Assert.IsNull(storedHeader);
     }
 }
コード例 #18
0
        public void AddGetTest()
        {
            using (var store = new InMemoryEntityTagStore())
            {
                var cacheKey = new CacheKey(Url, new[] { "Accept" });

                var headerValue = new TimedEntityTagHeaderValue("\"abcdefghijkl\"");
                store.AddOrUpdate(cacheKey, headerValue);
                TimedEntityTagHeaderValue storedHeader;
                Assert.True(store.TryGetValue(cacheKey, out storedHeader));
                Assert.AreEqual(headerValue.ToString(), storedHeader.ToString());                
            }
        }
コード例 #19
0
        public void AddOrUpdate(CacheKey key, TimedEntityTagHeaderValue eTag)
        {
            _eTagCache.Set(key.HashBase64, eTag, DateTimeOffset.MaxValue);

            // route pattern
            var bag = new ConcurrentBag<CacheKey>();
            bag = (ConcurrentBag<CacheKey>)_routePatternCache.AddOrGetExisting(key.RoutePattern, bag
                , DateTimeOffset.MaxValue) ?? bag;
            bag.Add(key);

            // resource
            var rbag = new ConcurrentBag<CacheKey>();
            rbag = (ConcurrentBag<CacheKey>)_resourceCache.AddOrGetExisting(key.ResourceUri, rbag
                , DateTimeOffset.MaxValue) ?? rbag;
            rbag.Add(key);
        }
コード例 #20
0
        public bool TryGetValue(CacheKey key, out TimedEntityTagHeaderValue eTag)
        {
            eTag = null;
            var operationResult = _memcachedClient.ExecuteGet<string>(key.HashBase64);
            if (!operationResult.Success || !operationResult.HasValue ||
                string.IsNullOrEmpty(operationResult.Value))
            {
                return false;
            }

            var value = operationResult.Value;
            if (!TimedEntityTagHeaderValue.TryParse(value, out eTag))
                return false;

            return true;
        }
コード例 #21
0
ファイル: NestEntityTagStore.cs プロジェクト: yyf919/CacheCow
        public bool TryGetValue(CacheKey key, out TimedEntityTagHeaderValue eTag)
        {
            eTag = null;
            var persistentCacheKey = TryGetPersistentCacheKey(key.HashBase64);
            if (persistentCacheKey != null)
            {
                eTag = new TimedEntityTagHeaderValue(persistentCacheKey.ETag)
                {
                    LastModified = persistentCacheKey.LastModified
                };

                return true; 
            }
                
            return false;
        }
コード例 #22
0
        public void RemoveByIdTest()
        {
            var cacheKey = new CacheKey("/api/Cars", new[] { "1234", "abcdef" });
            var store = new SqlServerEntityTagStore();
            var value = new TimedEntityTagHeaderValue("\"abcdef1234\"") { LastModified = DateTime.Now };

            // first remove them
            store.RemoveAllByRoutePattern(cacheKey.RoutePattern);

            // add
            store.AddOrUpdate(cacheKey, value);

            // delete
            Assert.True(store.TryRemove(cacheKey));
            Assert.True(!store.TryRemove(cacheKey));
        }
コード例 #23
0
 public void AddOrUpdate(CacheKey key, TimedEntityTagHeaderValue eTag)
 {
     using (var connection = new SqlConnection(_connectionSting))
     using (var command = new SqlCommand())
     {
         connection.Open();
         command.Connection = connection;
         command.CommandText = StoredProcedureNames.AddUpdateCache;
         command.CommandType = CommandType.StoredProcedure;
         command.Parameters.AddWithValue(ColumnNames.CacheKeyHash, key.Hash);
         command.Parameters.AddWithValue(ColumnNames.RoutePattern, key.RoutePattern);
         command.Parameters.AddWithValue(ColumnNames.ETag, eTag.Tag);
         command.Parameters.AddWithValue(ColumnNames.LastModified, eTag.LastModified);
         command.ExecuteNonQuery();
     }
 }
コード例 #24
0
ファイル: IntegrationTests.cs プロジェクト: Nangal/CacheCow
        public void RemoveByIdResourceUri()
        {
            var cacheKey = new CacheKey("/api/Cars/123", new[] { "1234", "abcdef" }, "111");
            var cacheKey2 = new CacheKey("/api/Cars/123", new[] { "1234", "abcdefgh", "222" });
            var store = new SqlServerEntityTagStore();
            var value = new TimedEntityTagHeaderValue("\"abcdef1234\"") { LastModified = DateTime.Now };

            // first remove them
            store.RemoveAllByRoutePattern(cacheKey.RoutePattern);

            // add
            store.AddOrUpdate(cacheKey, value);
            store.AddOrUpdate(cacheKey2, value);

            // delete
            Assert.AreEqual(2, store.RemoveResource("/api/Cars/123"));
        }
コード例 #25
0
        public void AddOrUpdate(CacheKey key, TimedEntityTagHeaderValue eTag)
        {
            _database.StringSet(key.HashBase64, eTag.ToString(), _expiry);
            
            // resource
            var resourceKey = string.Format(ResourceFormat, key.ResourceUri);
            _database.SetAdd(resourceKey, key.HashBase64);
            if (_expiry.HasValue)
                _database.KeyExpire(resourceKey, _expiry);

            // routePattern
            var routePatternKey = string.Format(RoutePatternFormat, key.RoutePattern);
            _database.SetAdd(routePatternKey, key.HashBase64);
            if (_expiry.HasValue)
                _database.KeyExpire(routePatternKey, _expiry);

        }
コード例 #26
0
		public bool TryGetValue(CacheKey key, out TimedEntityTagHeaderValue eTag)
		{
			eTag = null;
			using (var session = _documentStore.OpenSession())
			{
				var cacheKey = session.Query<PersistentCacheKey>()
					.Customize(x => x.WaitForNonStaleResultsAsOfNow())
					.FirstOrDefault(x => x.Hash == key.Hash);
				if (null == cacheKey)
					return false;

				eTag = new TimedEntityTagHeaderValue(cacheKey.ETag)
				{
					LastModified = cacheKey.LastModified
				};
				return true;
			}
		}
コード例 #27
0
		public bool TryGetValue(CacheKey key, out TimedEntityTagHeaderValue eTag)
		{
			eTag = null;

			using (var connection = new MongoEntityStoreConnection(this.connectionString))
			{
				var cacheKey = connection.DocumentStore.AsQueryable().FirstOrDefault(x => x.Hash == key.Hash);
				if (null == cacheKey)
					return false;

				eTag = new TimedEntityTagHeaderValue(cacheKey.ETag)
				{
					LastModified = cacheKey.LastModified
				};

				return true;
			}
		}
コード例 #28
0
ファイル: IntegrationTests.cs プロジェクト: Nangal/CacheCow
        public void AddTest()
        {
            var cacheKey = new CacheKey("/api/Cars", new[] {"1234", "abcdef"});
            var store = new SqlServerEntityTagStore();
            var value = new TimedEntityTagHeaderValue("\"abcdef1234\"") {LastModified = DateTime.Now};

            // first remove them
            store.RemoveAllByRoutePattern(cacheKey.RoutePattern);

            // add
            store.AddOrUpdate(cacheKey, value);

            // get
            TimedEntityTagHeaderValue dbValue;
            store.TryGetValue(cacheKey, out dbValue);

            Assert.AreEqual(value.Tag, dbValue.Tag);
            Assert.AreEqual(value.LastModified.ToString(), dbValue.LastModified.ToString());
        }
コード例 #29
0
        public void AddRemoveByPatternTest()
        {

            const string RoutePattern = "stuff";

            using (var store = new InMemoryEntityTagStore())
            {
                var cacheKey = new CacheKey(Url, new[] { "Accept" }, RoutePattern);
                var cacheKey2 = new CacheKey(Url + "/chaja", new[] { "Accept" }, RoutePattern);
                var headerValue = new TimedEntityTagHeaderValue("\"abcdefghijkl\"");
                store.AddOrUpdate(cacheKey, headerValue);
                store.AddOrUpdate(cacheKey2, headerValue);
                store.RemoveAllByRoutePattern(RoutePattern);
                store.TryRemove(cacheKey);
                TimedEntityTagHeaderValue storedHeader;
                Assert.False(store.TryGetValue(cacheKey, out storedHeader));
                Assert.False(store.TryGetValue(cacheKey2, out storedHeader));
                Assert.IsNull(storedHeader);
            }
        }
コード例 #30
0
        public bool TryGetValue(CacheKey key, out TimedEntityTagHeaderValue eTag)
        {
            eTag = null;

            if (key == null)
            {
                return false;
            }

            var operationResult = _memcachedClient.Get<string>(key.HashBase64);
            if (operationResult == null)
            {
                return false;
            }

            var value = operationResult;
            if (!TimedEntityTagHeaderValue.TryParse(value, out eTag))
                return false;

            return true;
        }
コード例 #31
0
        public void RemoveByIdRoutePattern()
        {
            var cacheKey = new CacheKey("/api/Cars", new[] { "1234", "abcdef" });
            var cacheKey2 = new CacheKey("/api/Cars", new[] { "1234", "abcdefgh" });
            var documentStore = new EmbeddableDocumentStore()
            {
                RunInMemory = true
            }.Initialize();

            var store = new RavenDbEntityTagStore(documentStore);
            var value = new TimedEntityTagHeaderValue("\"abcdef1234\"") { LastModified = DateTime.Now };

            // first remove them
            store.RemoveAllByRoutePattern(cacheKey.RoutePattern);

            // add
            store.AddOrUpdate(cacheKey, value);
            store.AddOrUpdate(cacheKey2, value);

            // delete
            Assert.AreEqual(2, store.RemoveAllByRoutePattern("/api/Cars"));
        }