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