1

正在构建本地化应用程序。所有数据都需要以不同的语言提供。作为存储模型,我尝试使用Nhibernate,因为它比Entity Framework有更好的性能。我将一个根节点存储在数据库中以获取实体的唯一标识,然后使用每种语言的子节点(语言环境表)创建第二个表。在Nhibernate中映射本地化表格

我的数据库表如下所示:

Country 
    Int Id; 
Country_Locale 
    Int Id; 
    Int CountryId; 
    String LangCode; 
    String Name; 

City 
    Int Id; 
    Int CountryId; 
City_Locale 
    Int Id; 
    Int CityId; 
    String LangCode; 
    String Name; 

我的首选实体会是什么样子

Country 
    Int Id (from Coutry table) 
    String LangCode (from locale table) 
    String Name (from locale table) 
    IList<City> Cities (Referenced to City entity) 
City 
    Int Id (From City table) 
    String LangCode (from locale table) 
    String Name (from locale table) 
    Country Country (Referenced to Country entity) 
    Int CountryId (From country table) 

我意识到,我不能映射以上,但它是一种结构我宁愿。我怎么能做这个映射或者有其他建议。

** 编辑数据库表格布局使其更加清晰。

回答

1

我采取了类似的方法来与你单独的表的第一次尝试,并最终我还是坚持了下来,而且合作的很好。这里是我的流利的映射文件(我使用功能NHibernate)和检索数据备份出来的数据库的一些示例代码:

using FluentNHibernate.Mapping; 

namespace Core.Mapping 
{  
    public class CountryMap : ClassMap<Country> 
    { 
     public CountryMap() 
     { 
      Id(x => x.Id); 

      Map(x => x.IsoCode) 
       .Length(2) 
       .Not.Nullable(); 

      HasMany(x => x.Translations) 
       .Fetch.Join() 
       .Not.LazyLoad() 
       .Cascade.AllDeleteOrphan(); 
     } 
    } 
} 

乡村翻译实际上被存储为一个单独的类/表,我意识到不是你正在寻找的东西,但它工作得很好,因为最后你有一个表,其中所有的翻译存储在。这里有流利的映射类:

using FluentNHibernate.Mapping; 

namespace Core.Mapping 
{ 
    public class CountryTranslationMap : ClassMap<CountryTranslation> 
    { 
     public CountryTranslationMap() 
     { 
      Id(x => x.Id); 

      Version(x => x.LastModified); 

      Map(x => x.Culture) 
       .Length(2) 
       .Not.Nullable(); 

      Map(x => x.Name) 
       .Length(50) 
       .Not.Nullable(); 

      References(x => x.Country); 
     } 
    } 

}

下面是从我的数据访问层一些例子供无论是文化或ISO代码(在这里我使用NHibernate的QueryOver语法)检索国家:

public IList<Country> GetAll(string culture) 
    { 
     var countryLanguageValue = new CountryTranslation(); 

     IList<Country> results = UnitOfWork.CurrentSession.QueryOver<Country>() 
      .Fetch(x => x.Translations).Eager 
      .JoinAlias(q => q.Translations,() => countryLanguageValue, JoinType.LeftOuterJoin) 
      .Where(() => countryLanguageValue.Culture == culture) 
      .OrderBy(x => x.DisplayOrder).Asc 
      .List(); 

     return results; 

    } 

    public Country GetCountryByIsoCode(string isoCode) 
    { 
     var result = UnitOfWork.CurrentSession.QueryOver<Country>() 
      .Where(x => x.IsoCode == isoCode) 
      .List() 
      .FirstOrDefault(); 

     return result; 
    } 
+0

感谢您的回答。我已经在寻找类似的方法。它确实工作得很好。我喜欢这种渴望加载的东西,确实非常方便/在这种情况下需要(我还没有实现。) – Patrick 2013-04-14 16:46:30

+0

@帕特里克 - 高兴地帮忙! – 2013-04-14 22:49:17

0

您可以将自己的计算属性添加到您的实体中,以检索城市的子国家/地区的CountryId,并在City对象上具有CountryId属性,因为该映射器将用实际的国家实体替换该Id字段。

public int CountryId { get { return this.Country.Id; } } 

不幸的是,我认为自动映射将是一个痛苦,如果你继续_一些前缀(什么似乎是unnecessary-我),其他数据库的表,但没有;如果你能消除你的表格看起来非常成熟的自动映射为自己的维基本指南中解释说:

https://github.com/jagregory/fluent-nhibernate/wiki/Auto-mapping

0

我想,这里的棘手的事情是,你希望你的CountryIdCity实体访问。我不明白为什么,因为你已经参考了你的国家,只需要从City开始做Country.Id就可以了。

var countryID = myCityEntity.Country.Id; 

顺便说一句,如果你需要这样的一些特定的原因,你甚至都不需要映射它,只是觉得在Domain Drive Design的方式,而不是简单的波苏斯,让实体做到这一点。

public int CountryId { 
    get { 
     return this.Country.Id; 
    } 
} 
+0

感谢您的答复,但在映射的这一部分,我不看,但在做基础的2代数据库表一类,使物体更自然的工作。所以我现在每个实体都有一个表和一个localizatoin表。在班级中,我更喜欢有1班。 – Patrick 2013-04-05 10:00:40