1

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

我的数据库表如下所示:

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)

我意识到我无法映射上述内容,但这是我更喜欢的一种结构。我怎么能做这个映射或有其他建议。

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

4

3 回答 3

1

我对您第一次尝试使用单独的表格采取了类似的方法,最后我坚持使用它并且效果很好。这是我的 Fluent 映射文件(我使用的是 Fluent 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();
        }
    }
}

国家/地区的翻译实际上存储为一个单独的类/表,我意识到这并不完全是您正在寻找的,但它工作得很好,因为最后您有一个存储所有翻译的表。以下是 Fluent 映射类:

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;
    }
于 2013-04-14T01:57:05.357 回答
0

我想这里的棘手之处在于您希望您CountryId可以从City实体访问。我不明白为什么,因为您已经提到了您的国家,并且只需Country.Id从您的国家中进行操作,您City就会拥有它。

var countryID = myCityEntity.Country.Id;

顺便说一句,如果您出于某种特定原因需要它,您甚至不需要映射它,只需以域驱动设计方式而不是普通 POCO 的方式思考,并让实体执行此操作。

public int CountryId {
    get {
        return this.Country.Id;
    }
}
于 2013-04-01T21:43:27.933 回答
0

您可以将自己的计算属性添加到您的实体中,以从 City 的子 Country 中检索 CountryId 等内容,并在 City 对象上拥有 CountryId 属性,因为映射器将用实际 Country 实体替换该 Id 字段。

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

不幸的是,我认为如果您在某些(对我来说似乎是不必要的)、数据库表而不是其他表上保留 _ 前缀,那么自动映射会很痛苦;如果您可以消除您的表看起来非常适合自动映射,如本指南在其 wiki 中所述:

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

于 2013-03-30T02:02:07.797 回答