我正在开发一种多语言ASP.NET MVC应用程序(MVC4)。

我想使我的资源文件字符串在运行时可编辑,而无需重新编译应用程序且不回收应用程序池,而且.resx文件看起来不太可能,因此我迁移到数据库中存储字符串资源。

我必须从数据库中获取每个标签/字符串资源,因此对于每个请求,数据库的命中都会增加该如何解决?

我到处搜索,有人建议将资源加载到字典中,并在登录/登录页面上将其存储为应用程序变量,然后将该字典用作资源而不是数据库命中。

我很困惑,什么是有效的方法?有人可以指导我正确使用以避免更多数据库访问吗?

任何帮助/建议将不胜感激。

谢谢

最佳答案

使用.resx文件进行本地化时,我遇到了同样的问题。当从事翻译的人不是程序员时,他们的表现就不好。现在,我们在管理区域中有一个翻译页面。效果很好。

我们仍然没有一个好的解决方案的领域是数据注释,它仍然使用.resx文件。我整理了以下源代码,以删除对我们实际数据库结构或表的任何引用。

如果数据库中不存在某个条目,则使用基础.resx文件会有一个回退。如果.resx文件中没有条目,则每当找到一个大写字母时,我都会拆分该单词(CamelSpace是字符串扩展方法)。

最后,根据您的实现,您可能需要删除上下文缓存,尤其是在缓存超出流程的情况下。

用法示例:

@LanguageDb.Translate("Enter your first name below","FirstNamePrompt")

@LanguageDb.Me.FirstName

@String
    .Format(LanguageDb
                .Translate(@"You can be insured for
                      {0} down and {1} payments of {2}"),
            Model.Down,Model.NumPayments,
            Model.InstallmentAmount)



public class LanguageDb : DynamicObject
{
    public static dynamic Me = new LanguageDb();
    private LanguageDb() { }

    public static string Translate(string englishPhrase, string resourceCode = null)
    {
        return GetTranslation(englishPhrase, resourceCode) ?? englishPhrase;
    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = GetTranslation(binder.Name);
        return true;
    }

    private static string GetTranslation(string resourceName, string resourceCode = null)
    {
        resourceCode = resourceCode ?? resourceName;
        if (resourceCode.Contains(" ") || resourceCode.Length > 50)
        {
            resourceCode = resourceName.GetHashCode().ToString(CultureInfo.InvariantCulture);
        }
        var lang = (string)HttpContext.Current.Request.RequestContext.RouteData.Values["lang"] ?? "en";

        // cache entries for an hour
        var result = Get(subagent + "_" + lang + "_" + resourceCode, 3600, () =>
        {
            // cache a datacontext object for 30 seconds.
            var context = Get("_context", 30, () => new YourDataContext()) as YourDataContext;
            var translation = context.Translations.FirstOrDefault(row => row.lang == lang && row.Code == resourceCode);
            if (translation == null)
            {
                translation = new Lookup {
                    Code = resourceCode,
                    lang = lang,
                    Value = Language.ResourceManager.GetString(resourceName, Language.Culture)
                                    ?? resourceName.CamelSpace()
                };
                context.Translations.Add(translation);
                context.SaveChanges();
            }

            return translation.Value;
        });

        return result;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        // ignore this
        return true;
    }

    public static T Get<T>(string cacheId, int secondsToCache, Func<T> getItemCallback) where T : class
    {
        T item = HttpRuntime.Cache.Get(cacheId) as T;
        if (item == null)
        {
            item = getItemCallback();
            if (secondsToCache > 0)
            {
                HttpRuntime.Cache.Insert(
                    cacheId, item, null, Cache.NoAbsoluteExpiration,
                    new TimeSpan(0, 0, secondsToCache), CacheItemPriority.Normal, null);
            }
            else
            {
                HttpRuntime.Cache.Insert(cacheId, item);
            }
        }
        return item;
    }
}

10-02 15:57
查看更多