{"id":19100968,"url":"https://github.com/thomaslevesque/Extensions.Caching.Extras","last_synced_at":"2025-04-18T18:31:23.042Z","repository":{"id":56538380,"uuid":"173960465","full_name":"thomaslevesque/Extensions.Caching.Extras","owner":"thomaslevesque","description":"Adds features to Microsoft.Extensions.Caching such as partitioning and eviction","archived":false,"fork":false,"pushed_at":"2020-11-01T22:22:44.000Z","size":30,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-04T23:06:33.208Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thomaslevesque.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-05T14:21:01.000Z","updated_at":"2020-10-17T21:09:54.000Z","dependencies_parsed_at":"2022-08-15T20:31:43.520Z","dependency_job_id":null,"html_url":"https://github.com/thomaslevesque/Extensions.Caching.Extras","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomaslevesque%2FExtensions.Caching.Extras","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomaslevesque%2FExtensions.Caching.Extras/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomaslevesque%2FExtensions.Caching.Extras/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomaslevesque%2FExtensions.Caching.Extras/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thomaslevesque","download_url":"https://codeload.github.com/thomaslevesque/Extensions.Caching.Extras/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223783094,"owners_count":17201905,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T03:53:05.294Z","updated_at":"2025-04-18T18:31:23.029Z","avatar_url":"https://github.com/thomaslevesque.png","language":"C#","funding_links":[],"categories":["others"],"sub_categories":[],"readme":"# Extensions.Caching.Extras\n\n[![NuGet version](https://img.shields.io/nuget/v/Extensions.Caching.Extras.svg?logo=nuget)](https://www.nuget.org/packages/Extensions.Caching.Extras)\n[![AppVeyor build](https://img.shields.io/appveyor/ci/thomaslevesque/extensions-caching-extras.svg?logo=appveyor\u0026logoColor=cccccc)](https://ci.appveyor.com/project/thomaslevesque/extensions-caching-extras)\n[![AppVeyor tests](https://img.shields.io/appveyor/tests/thomaslevesque/extensions-caching-extras.svg?logo=appveyor\u0026logoColor=cccccc)](https://ci.appveyor.com/project/thomaslevesque/extensions-caching-extras/build/tests)\n\nAdds features to Microsoft.Extensions.Caching such as partitioning and eviction.\n\n## Partitioning\n\n`IMemoryCache` is registered as a singleton, which means it's shared by the whole\napplication. So you need to be careful to avoid key collisions. Consider this scenario:\n- a `ProductManager` class uses product ids as cache keys for products\n- a `CustomerManager` class uses customer ids as cache keys for customers. If a product\nand a customer have the same id (which can easily happen if you use integer ids), they\nwill have the same cache key. So you could end up retrieving a product when you try to\nget a customer from the cache, or vice versa.\n\nA simple solution to this problem is to use a prefix for the cache key, for instance\nsomething like `$\"Products/{id}\"`. But it's tedious to add the prefix every time you\nneed to access the cache...\n\nThe `Partition` method gives you a memory cache that is a \"subset\" of the global\ncache. Just pass a \"partition key\" to the `Partition` method:\n\n```csharp\npublic class ProductManager\n{\n    private readonly IMemoryCache _cache;\n\n    public ProductManager(IMemoryCache cache)\n    {\n        _cache = cache.Partition(\"Products\");\n    }\n    \n    ...\n}\n```\nWhen you need to get a product from the cache, you no longer need to add a prefix:\njust pass the product id, and you won't get collisions with other parts of the code\nusing the same global cache (unless they use the same partition key, of course).\n\nYou can also use nested partitions. For instance, in a multitenant application, you\nmight want to partition the cache by tenant, to ensure you never access a tenant's\ndata from another tenant:\n\n```csharp\n    public ProductManager(IMemoryCache cache, ITenantContext tenantContext)\n    {\n        _cache = cache.Partition(tenantContext.TenantKey)\n                      .Partition(\"Products\");\n    }\n```\n\nThe partition key can be of any type that implements `Equals` and `GetHashCode`\ncorrectly. The previous examples used `String`, but sometimes it makes sense to\nuse `Type`. There's a generic overload of `Partition` for partitioning by\ntype:\n\n```csharp\n    public ProductManager(IMemoryCache cache)\n    {\n        _cache = cache.Partition\u003cProductManager\u003e();\n    }\n```\nThis gives you a cache partition whose key is `typeof(ProductManager)`.\n\n## Eviction\n\nOut of the box, there's no way to clear a memory cache. You can only remove items one\nby one, assuming you know their keys. The `WithEviction` method provides this\nfunctionality:\n\n```csharp\npublic class MyClass\n{\n    private readonly IEvictableMemoryCache _cache;\n    \n    public MyClass(IMemoryCache cache)\n    {\n        _cache = cache.WithEviction();\n    }\n    \n    public void ClearCache()\n    {\n        _cache.EvictAll();\n    }\n    \n    ...\n}\n```\n\n*Note: only entries added via an evictable cache will actually be removed. Any cache\nentry added directly via the normal memory cache will be unaffected.*\n\nClearing the whole cache is rarely useful, but it can be useful to clear a subset of\nit. To do this, you can combine the partitioning and eviction features:\n\n```csharp\n_cache = cache.Partition(\"Products\").WithEviction();\n...\n\n// Only clears the \"Products\" partition\n_cache.EvictAll();\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomaslevesque%2FExtensions.Caching.Extras","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomaslevesque%2FExtensions.Caching.Extras","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomaslevesque%2FExtensions.Caching.Extras/lists"}