Strawberry Shake客户端CacheAndNetwork策略离线未读缓存问题求助
问题分析与解决方案
代码遗漏的关键配置
你的代码确实缺少两项核心配置,导致离线时无法回退到本地缓存:
- 未配置本地缓存存储:Strawberry Shake需要显式指定缓存实现(内存或持久化),否则缓存策略无法生效。
- 未处理网络请求异常:默认HttpClient会直接抛出
HttpRequestException,不会自动回退到缓存,需要配置客户端允许网络失败时返回缓存数据。
你的预期是正确的:CacheAndNetwork策略的设计逻辑就是优先返回缓存数据,同时后台请求网络更新缓存;当网络不可用时,应直接返回现有缓存。
修正后的示例代码
第一步:安装必要的NuGet包
确保已安装以下包(以内存缓存为例):
Install-Package StrawberryShake.Transport.Http Install-Package StrawberryShake.Caching.InMemory
第二步:完整客户端代码
namespace strawberry_shake_graphql_client { internal class Program { static async Task Main(string[] args) { var serviceCollection = new ServiceCollection(); serviceCollection // 注册内存缓存存储(如需持久化可替换为Sqlite缓存) .AddInMemoryCache() // 配置Strawberry Shake客户端及缓存策略 .AddStrawberryShakeGraphQLClient(StrawberryShake.ExecutionStrategy.CacheAndNetwork) .ConfigureHttpClient(client => { client.BaseAddress = new Uri("https://localhost:7148/graphql/"); // 允许网络错误转为GraphQL错误,而非直接抛出异常 client.DefaultRequestPolicy = new HttpPolicy { AllowNetworkErrors = true }; }) // 配置缓存过期规则 .ConfigureCache(options => { options.DefaultExpiration = TimeSpan.FromHours(1); }); var serviceProvider = serviceCollection.BuildServiceProvider(); var client = serviceProvider.GetRequiredService<IStrawberryShakeGraphQLClient>(); while (Console.ReadLine() != string.Empty) { await GetBooks(client); } } static async Task GetBooks(IStrawberryShakeGraphQLClient client) { try { var result = await client.Getbooks.ExecuteAsync(); if (result.IsErrorResult()) { // 检查是否为网络错误,尝试读取缓存 var hasNetworkError = result.Errors.Any(e => e.Message.Contains("network") || e.Message.Contains("HttpRequestException")); if (hasNetworkError) { var cachedResult = await client.Getbooks.ReadFromCacheAsync(); if (cachedResult?.Data != null) { Console.WriteLine("使用本地缓存数据:"); foreach (var book in cachedResult.Data.BooksList) { Console.WriteLine(book.Title); } return; } Console.WriteLine("网络错误且无本地缓存数据"); return; } Console.WriteLine("查询执行错误:" + string.Join(", ", result.Errors.Select(e => e.Message))); return; } Console.WriteLine("使用最新网络数据:"); foreach (var book in result.Data.BooksList) { Console.WriteLine(book.Title); } } catch (HttpRequestException ex) { // 兜底捕获网络异常,尝试读取缓存 var cachedResult = await client.Getbooks.ReadFromCacheAsync(); if (cachedResult?.Data != null) { Console.WriteLine("网络不可用,使用本地缓存数据:"); foreach (var book in cachedResult.Data.BooksList) { Console.WriteLine(book.Title); } } else { Console.WriteLine($"网络不可用且无缓存数据:{ex.Message}"); } } } } }
关键配置说明
AddInMemoryCache():注册内存缓存,若需进程重启后保留缓存,可替换为AddSqliteCache(options => options.ConnectionString = "Data Source=cache.db")。HttpPolicy.AllowNetworkErrors = true:将网络错误转换为GraphQL错误,让Strawberry Shake可以处理并触发缓存回退逻辑。ReadFromCacheAsync():网络请求失败时,主动从缓存读取历史查询结果。CacheAndNetwork策略:在线时优先返回缓存,后台异步更新缓存;离线时直接返回已缓存的数据(若存在)。
内容的提问来源于stack exchange,提问作者Siraf
相关产品推荐
相关产品推荐

