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

在 session 結束時把已完成工作、待辦事項與經驗寫入交接檔案,並在 session 開始時重新載入。

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 個月前更新