Caching

codewithmukesh/dotnet-claude-kit/skills/caching

作者 codewithmukesh23300897f4d1无许可证754 个星标收录于 2026年10月8日更新于 2026年10月8日仓库2个月前更新

Caching strategies for .NET 10 applications. Covers HybridCache (the default), output caching, response caching, and distributed cache patterns. Load this skill when implementing caching, optimizing read performance, reducing database load, or when the user mentions "cache", "HybridCache", "Redis", "output cache", "response cache", "distributed cache", "IMemoryCache", "cache invalidation", "stampede protection", or "cache-aside".

AI 生成的概览

面向 .NET 10 应用的缓存策略指南,涵盖 HybridCache、输出缓存、响应缓存与分布式缓存模式。

功能
该技能为在 .NET 10 应用中实现缓存提供参考指导与代码示例。内容涵盖作为推荐默认方案的 HybridCache、用于完整 HTTP 响应的输出缓存、写入时的缓存失效,以及传统的 cache-aside 模式。它还列出反模式,例如不设过期时间的缓存、以全局键缓存可变的用户专属数据、自行实现防击穿保护,并提供将场景映射到建议的决策指南。
适用场景
在实现缓存、优化读取性能、降低数据库负载时使用,或在用户提到 cache、HybridCache、Redis、output cache、response cache、distributed cache、IMemoryCache、cache invalidation、stampede protection 或 cache-aside 时使用。
运行要求
无需脚本或工具,仅为说明性内容。示例假定使用 .NET 10 应用,并可选地使用 Redis 实例作为 L2 分布式缓存。

Caching

Core Principles

  1. HybridCache is the default — .NET 9+ introduced HybridCache as the unified caching abstraction. It combines in-memory (L1) and distributed (L2) caching with stampede protection. See ADR-004.
  2. Cache reads, not writes — Cache GET operations. Invalidate on mutations. Never cache POST/PUT/DELETE responses.
  3. Output caching for entire responses — When the full HTTP response can be cached (public APIs, static data), use output caching middleware.
  4. Set explicit TTLs — Every cached item needs an expiration. No unbounded caches.

Patterns

HybridCache (Recommended Default)

csharp
// Program.csbuilder.Services.AddHybridCache(options =>{    options.DefaultEntryOptions = new HybridCacheEntryOptions    {        Expiration = TimeSpan.FromMinutes(5),        LocalCacheExpiration = TimeSpan.FromMinutes(2)    };});
// Optional: Add Redis as the L2 distributed cachebuilder.Services.AddStackExchangeRedisCache(options =>{    options.Configuration = builder.Configuration.GetConnectionString("Redis");});
csharp
// Usage in a handlerpublic class GetProduct{    public record Query(Guid Id);    public record Response(Guid Id, string Name, decimal Price);
    internal class Handler(AppDbContext db, HybridCache cache)    {        public async Task<Response?> Handle(Query query, CancellationToken ct)        {            return await cache.GetOrCreateAsync(                $"products:{query.Id}",                async token => await db.Products                    .Where(p => p.Id == query.Id)                    .Select(p => new Response(p.Id, p.Name, p.Price))                    .FirstOrDefaultAsync(token),                new HybridCacheEntryOptions                {                    Expiration = TimeSpan.FromMinutes(10)                },                cancellationToken: ct);        }    }}

Cache Invalidation

csharp
// Invalidate on mutationpublic class UpdateProduct{    internal class Handler(AppDbContext db, HybridCache cache)    {        public async Task<Result> Handle(Command command, CancellationToken ct)        {            var product = await db.Products.FindAsync([command.Id], ct);            if (product is null) return Result.Failure("Product not found");
            product.Update(command.Name, command.Price);            await db.SaveChangesAsync(ct);
            // Invalidate the cached entry            await cache.RemoveAsync($"products:{command.Id}", ct);
            return Result.Success();        }    }}

Output Caching (Full Response Caching)

csharp
// Program.csbuilder.Services.AddOutputCache(options =>{    options.AddBasePolicy(b => b.NoCache()); // Don't cache by default
    options.AddPolicy("ProductList", b => b        .Expire(TimeSpan.FromMinutes(5))        .Tag("products"));
    options.AddPolicy("ProductById", b => b        .Expire(TimeSpan.FromMinutes(10))        .SetVaryByRouteValue("id")        .Tag("products"));});
app.UseOutputCache();
// Apply to endpointsgroup.MapGet("/", ListProducts).CacheOutput("ProductList");group.MapGet("/{id:guid}", GetProduct).CacheOutput("ProductById");
// Invalidate by tag on mutationsgroup.MapPut("/{id:guid}", async (Guid id, UpdateProductRequest request,    IOutputCacheStore store, CancellationToken ct) =>{    // ... update logic ...    await store.EvictByTagAsync("products", ct);    return TypedResults.NoContent();});

Cache-Aside Pattern (Legacy)

Prefer HybridCache for all new code. Manual IDistributedCache cache-aside lacks stampede protection, requires manual serialization, and has no L1/L2 layering. Use only when integrating with existing code that already uses IDistributedCache directly.

Anti-patterns

Don't Cache Without Expiration

csharp
// BAD — cache lives forever, stale data guaranteedawait cache.SetStringAsync(key, value);
// GOOD — always set TTLawait cache.SetStringAsync(key, value, new DistributedCacheEntryOptions{    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)});

Don't Cache Mutable User-Specific Data

csharp
// BAD — caching user's cart with a global keyawait cache.GetOrCreateAsync("shopping-cart", ...);
// GOOD — include user ID in keyawait cache.GetOrCreateAsync($"shopping-cart:{userId}", ...);

Don't Build Your Own Stampede Protection

csharp
// BAD — manual lock to prevent cache stampedeprivate static readonly SemaphoreSlim Lock = new(1, 1);await Lock.WaitAsync();try { /* check cache, populate if missing */ }finally { Lock.Release(); }
// GOOD — HybridCache has built-in stampede protectionawait hybridCache.GetOrCreateAsync(key, factory);

Decision Guide

ScenarioRecommendation
General data cachingHybridCache (GetOrCreateAsync)
Full HTTP responseOutput caching with .CacheOutput()
Frequently read, rarely writtenHybridCache with longer TTL
User-specific dataHybridCache with user-scoped key
Cache invalidation on writecache.RemoveAsync() or output cache tags
Distributed deploymentHybridCache + Redis L2 backend
Single-server deploymentHybridCache with in-memory only

来源与署名

来源:codewithmukesh/dotnet-claude-kit位于skills/caching提交2330089

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架

更多来自 codewithmukesh/dotnet-claude-kit 的技能

Wrap Up

codewithmukesh

在会话结束时把已完成工作、待办任务与经验写入交接文件,并在会话开始时重新载入。

Productivity & Workflow7542个月前更新

Workflow Mastery

codewithmukesh

Claude Code workflow mastery for .NET developers. Covers parallel execution with git worktrees, plan mode strategy, verification loops, auto-formatting hooks, permission setup for dotnet CLI, prompting techniques, subagent patterns, and context discipline — token budget management, MCP-first navigation, lazy loading, and subagent isolation — all adapted for the .NET ecosystem. Load this skill when setting up Claude Code for a .NET project, optimizing workflows, running parallel sessions, when context is running low or sessions feel sluggish, when exploring a large codebase efficiently, or when the user mentions "productivity", "workflow", "parallel", "worktree", "plan mode", "permissions", "hooks", "10x", "setup Claude Code", "speed up development", "context", "tokens", "budget", "running out of context", "too many files", or "large codebase". Inspired by tips from Boris Cherny (creator of Claude Code) and the Anthropic team.

待分类7542个月前更新

Vertical Slice

codewithmukesh

指导 .NET 开发者采用垂直切片架构组织应用,涵盖功能文件夹、端点分组与处理程序模式。

Software Development7542个月前更新

Testing

codewithmukesh

Testing strategy for .NET 10 applications. Covers xUnit v3, WebApplicationFactory for integration tests, Testcontainers for real database testing, Verify for snapshot testing, and the AAA pattern. Load this skill when writing tests, setting up test infrastructure, reviewing test coverage, or when the user mentions "test", "xUnit", "WebApplicationFactory", "Testcontainers", "integration test", "unit test", "bUnit", "snapshot test", "Verify", "test coverage", "AAA pattern", "WireMock", or "FakeTimeProvider".

待分类7542个月前更新

Tdd

codewithmukesh

Guided test-driven development workflow for .NET 10 using xUnit v3, WebApplicationFactory, Testcontainers, and Verify snapshots. Follows the strict red-green-refactor cycle. Use when: "TDD", "test-driven", "let's TDD this", "red green refactor", "write the test first", or when building a feature with clear acceptance criteria.

待分类7542个月前更新

Spec

codewithmukesh

通过结构化提问,把模糊的功能想法转化为双方确认并持久化的规格说明文件。

Productivity & Workflow7542个月前更新