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

从Razor视图提取HTML Helpers:.NET Core MVC对接旧翻译库问题

优化旧翻译表查询性能的实用方案

嘿,针对你在.NET Core 2.0 MVC应用中对接旧翻译表的性能问题(旧应用每次翻译都单独查数据库,效率太低了),结合数据库不可修改的限制,我整理了几个落地性强的优化方案,都是处理遗留系统时亲测有效的:

1. 预加载所有翻译到内存缓存

翻译数据通常属于低频变更的静态数据,最直接的优化就是启动时一次性加载所有翻译数据到内存,后续所有翻译请求直接从内存读取,彻底避免数据库调用。

实现思路:

  • 用线程安全的ConcurrentDictionary存储翻译映射,键用$"{languageId}_{translationId}"的组合,值为翻译文本。
  • 在应用启动阶段(比如Startup.cs的ConfigureServices里,或者用IHostedService异步加载)执行一次批量查询,把所有翻译数据填充到字典中。
  • 为应对翻译数据更新,可添加定时刷新机制(比如每隔几小时重新加载),或者提供手动刷新的后台接口(如果需要即时更新)。

代码示例:

public class TranslationCache
{
    private static ConcurrentDictionary<string, string> _translations = new ConcurrentDictionary<string, string>();
    private readonly YourDbContext _dbContext;

    public TranslationCache(YourDbContext dbContext)
    {
        _dbContext = dbContext;
        LoadTranslations();
    }

    private void LoadTranslations()
    {
        var allTranslations = _dbContext.Translations.ToList();
        foreach (var trans in allTranslations)
        {
            var key = $"{trans.LanguageId}_{trans.TranslationId}";
            _translations.TryAdd(key, trans.Text);
        }
    }

    public string GetTranslation(int languageId, int translationId)
    {
        var key = $"{languageId}_{translationId}";
        _translations.TryGetValue(key, out var text);
        return text ?? $"[Missing: {translationId}]";
    }

    // 可选:手动刷新缓存
    public void RefreshCache()
    {
        _translations.Clear();
        LoadTranslations();
    }
}

在Startup.cs里注册为单例:

services.AddSingleton<TranslationCache>();

2. 批量查询+请求级缓存

如果翻译数据量特别大(比如十万级以上),预加载到内存会占用过多资源,这时候可以采用批量查询+请求级缓存的方式:

实现思路:

  • 在服务层或视图助手类中,先收集当前请求需要的所有translationId和对应的languageId。
  • 一次性向数据库发起批量查询,获取所有需要的翻译数据。
  • 把查询结果缓存到当前请求的HttpContext.Items中,同一请求内的后续翻译请求直接从这里读取。

代码示例:

public class TranslationService
{
    private readonly YourDbContext _dbContext;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public TranslationService(YourDbContext dbContext, IHttpContextAccessor httpContextAccessor)
    {
        _dbContext = dbContext;
        _httpContextAccessor = httpContextAccessor;
    }

    public string GetTranslation(int languageId, int translationId)
    {
        var cacheKey = $"translations_{languageId}";
        if (!_httpContextAccessor.HttpContext.Items.TryGetValue(cacheKey, out var cacheObj))
        {
            // 这里可替换为当前请求收集到的translationId列表,减少不必要的查询
            var translations = _dbContext.Translations
                .Where(t => t.LanguageId == languageId)
                .ToDictionary(t => t.TranslationId, t => t.Text);
            _httpContextAccessor.HttpContext.Items[cacheKey] = translations;
            cacheObj = translations;
        }

        var translationDict = (Dictionary<int, string>)cacheObj;
        return translationDict.TryGetValue(translationId, out var text) ? text : $"[Missing: {translationId}]";
    }
}

3. 适配.NET Core本地化框架

如果想让翻译逻辑更贴合.NET Core MVC的生态,可以把旧翻译表适配到IStringLocalizer接口中,这样就能直接使用MVC的本地化标签,同时内部优化查询逻辑。

实现思路:

  • 自定义OldDbStringLocalizer类,实现IStringLocalizer接口。
  • 在GetString方法内部,复用预加载缓存或批量查询的方式获取翻译。
  • 注册自定义的本地化提供者,替换默认的资源文件本地化。

核心代码示例:

public class OldDbStringLocalizer : IStringLocalizer
{
    private readonly TranslationCache _translationCache;
    private readonly int _currentLanguageId;

    public OldDbStringLocalizer(TranslationCache translationCache, IHttpContextAccessor httpContextAccessor)
    {
        _translationCache = translationCache;
        // 从请求上下文获取当前语言ID(示例从Cookie读取,可替换为路由/Header等方式)
        _currentLanguageId = int.Parse(httpContextAccessor.HttpContext.Request.Cookies["LanguageId"] ?? "1");
    }

    public LocalizedString this[string name]
    {
        get
        {
            var translationId = int.TryParse(name, out var id) ? id : 0;
            var text = _translationCache.GetTranslation(_currentLanguageId, translationId);
            return new LocalizedString(name, text, text == $"[Missing: {translationId}]");
        }
    }

    // 实现其他接口方法(如GetAllStrings等)...
}

在Startup.cs中注册:

services.AddLocalization(options => options.ResourcesPath = "Resources");
services.AddSingleton<IStringLocalizer, OldDbStringLocalizer>();

之后在视图中就能直接使用:

<p>@Localizer["456"]</p>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:28:00