查询友好的域对象本地化

时间:2016-01-04 09:50:43

标签: c# entity-framework nhibernate localization

我需要设计一个存储部分多语言内容的应用程序;即一些域对象字段是可翻译的。 注意:我正在使用NHibernate,但这只是案例中的技术细节。

让我们考虑以下域模型:

public class Post {
    public virtual int Id {get; set;}
    public virtual User Author {get; set;}
    public virtual string Title {get; set;} // translatable
    public virtual string Content {get; set;}  // translatable
}
通过互联网我发现了几种方法,其中大多数都是黑客和丑陋的;许多完全不能接受。 大多数解决方案都基于向模型引入“特殊”字段,无论是Title_FR, Content_FR, Title_EN, Content_EN还是Dictionary<string, string> ContentTranslations

优点:

  • 易于查询(第一种情况)
  • 性能

缺点:

  • 在添加语言时需要更改架构(第一种情况)
  • 需要向模型中添加特殊字段

后来我设计了自己的解决方案(进一步调查,恰好是重新发明轮子),它拦截了NHibernate特定的事件;即,一旦域模型的实例填充了值,则可翻译字段将使用来自抽象翻译提供者的翻译值重新填充。

优点:

  • 无缝集成
  • 没有架构修改
  • 完全自动

缺点:

  • 无法查询翻译字段;对翻译字段进行过滤会导致奇怪的(从用户角度来看)行为

我正在寻找解决方案

  1. 可能无缝集成。没有特殊字段引入域模型
  2. 自动应用翻译
  3. 在更新(已翻译的)域对象时,注意不要覆盖原始值
  4. 正在查询友好;即,引入该机制不需要显着改变LINQ查询。这可能取消了“可加入”翻译表的资格
  5. 理想情况下,解决方案不应该破坏LINQ投影;然而,这可能只是要求太多(*)
  6. (*)关于5的解释。我正在广泛使用AutoMapper的Project.To(),以避免检索不必要的字段和SELECT N + 1问题。 我提出的解决方案不适用于投影,我相信使用投影时不会触发OnPostLoad事件

    有关该主题的任何推荐阅读?

1 个答案:

答案 0 :(得分:1)

我不确定你的数据库结构是怎样的。如果您不想使用IDictionary(我更喜欢),那么我建议实现LocalizableString类和相应的ICompositeUserTypeIUserType或使用组件映射。

public class Post {
    public virtual int Id {get; set;}
    public virtual User Author {get; set;}
    public virtual LocalizableString Title {get; set;} // translatable
    public virtual LocalizableString Content {get; set;}  // translatable
}

您可能还需要对linq提供程序实现一些扩展,以允许自定义查询操作。

要考虑的一些替代方法:

  • 使用公式列公式列用于本地化字段
  • 使用我自己的DelegateDecompiler来查询计算出的属性。