You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor客户端应用预加载数据库及本地搜索与数据同步方案咨询

Blazor客户端预加载数据缓存与同步最佳方案

针对你的需求,推荐基于单例缓存服务+线程安全集合的实现方案,既满足启动预加载、快速搜索,也能保证添加记录时的客户端与服务器数据同步。以下是具体实现步骤:

1. 选择合适的缓存存储结构

你尝试用字典是合理的,推荐升级为ConcurrentDictionary<TKey, TModel>:

  • 天然支持线程安全,避免Blazor客户端并发操作(比如搜索与添加同时进行)导致的异常
  • 基于键的查找性能接近O(1),完美适配快速搜索场景
  • 如果需要按非唯一字段搜索(比如按名称模糊匹配),可以额外维护辅助索引,比如Dictionary<string, List<TModel>>,提前将数据按搜索字段分组

2. 实现单例缓存服务

创建一个全局单例的缓存服务,负责数据预加载、缓存维护与服务器交互:

public class DataCacheService
{
    private readonly HttpClient _httpClient;
    // 主缓存:按记录ID作为键
    public ConcurrentDictionary<int, YourDataModel> MainCache { get; private set; } = new();
    // 辅助索引:按名称分组(示例)
    private readonly Dictionary<string, List<YourDataModel>> _nameIndex = new();

    public DataCacheService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    // 应用启动时初始化缓存
    public async Task InitializeCacheAsync()
    {
        var allRecords = await _httpClient.GetFromJsonAsync<List<YourDataModel>>("api/yourdataendpoint");
        if (allRecords == null) return;

        foreach (var record in allRecords)
        {
            MainCache.TryAdd(record.Id, record);
            // 更新辅助索引
            if (!_nameIndex.ContainsKey(record.Name))
            {
                _nameIndex[record.Name] = new List<YourDataModel>();
            }
            _nameIndex[record.Name].Add(record);
        }
    }

    // 添加记录并同步缓存
    public async Task AddRecordAsync(YourDataModel newRecord)
    {
        // 1. 先提交到服务器确保数据持久化
        var response = await _httpClient.PostAsJsonAsync("api/yourdataendpoint", newRecord);
        response.EnsureSuccessStatusCode();

        // 2. 获取服务器返回的完整记录(包含自动生成的ID等字段)
        var savedRecord = await response.Content.ReadFromJsonAsync<YourDataModel>();
        if (savedRecord == null) return;

        // 3. 更新本地缓存与辅助索引
        MainCache.TryAdd(savedRecord.Id, savedRecord);
        if (!_nameIndex.ContainsKey(savedRecord.Name))
        {
            _nameIndex[savedRecord.Name] = new List<YourDataModel>();
        }
        _nameIndex[savedRecord.Name].Add(savedRecord);
    }

    // 快速搜索方法示例
    public IEnumerable<YourDataModel> SearchByName(string name)
    {
        if (_nameIndex.TryGetValue(name, out var records))
        {
            return records;
        }
        // 模糊搜索 fallback
        return MainCache.Values.Where(r => r.Name.Contains(name, StringComparison.OrdinalIgnoreCase));
    }
}

3. 启动时预加载缓存

在Program.cs中注册单例服务,并在应用启动时触发缓存初始化:

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");

// 注册缓存服务为单例
builder.Services.AddSingleton<DataCacheService>();
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

var app = builder.Build();

// 初始化缓存(应用启动时执行)
var cacheService = app.Services.GetRequiredService<DataCacheService>();
await cacheService.InitializeCacheAsync();

await app.RunAsync();

4. 组件中使用缓存服务

在Blazor组件中注入缓存服务,直接使用缓存数据进行搜索,添加记录时调用服务方法自动同步:

@inject DataCacheService CacheService
@inject HttpClient Http

<h3>数据搜索</h3>
<input @bind="searchName" placeholder="输入名称搜索" />
<button @onclick="Search">搜索</button>

@foreach (var item in searchResults)
{
    <p>@item.Id - @item.Name</p>
}

<h3>添加新记录</h3>
<input @bind="newName" placeholder="输入新名称" />
<button @onclick="AddNewRecord">提交</button>

@code {
    private string searchName = string.Empty;
    private IEnumerable<YourDataModel> searchResults = Enumerable.Empty<YourDataModel>();
    private string newName = string.Empty;

    private void Search()
    {
        searchResults = CacheService.SearchByName(searchName);
    }

    private async Task AddNewRecord()
    {
        var newRecord = new YourDataModel { Name = newName };
        await CacheService.AddRecordAsync(newRecord);
        // 清空输入并刷新搜索结果
        newName = string.Empty;
        Search();
    }
}

关键注意事项

  • 内存占用:15000条记录如果单条数据不大(比如几百字节),客户端内存完全能承受;如果数据量过大,可以考虑分批次预加载或仅缓存核心搜索字段
  • 数据一致性:如果服务器存在其他修改数据的渠道(比如后台管理系统),客户端缓存会出现不一致,可扩展添加定时刷新缓存或SignalR实时推送更新的逻辑
  • 错误处理:实际代码中要添加异常捕获(比如API请求失败时的提示),避免缓存更新失败导致的逻辑异常

内容的提问来源于stack exchange,提问作者user27985104

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 20:55:12