关于nhibernate:FluentNHibernate-将一个类映射到多个表

FluentNHibernate - Mapping a class to multiple tables

很抱歉提一个冗长的问题。但是值得提供所有细节,因此请耐心等待直到最后。

我正在对我没有太多控制权的旧数据库进行工作。我希望能够将一个类映射到多个数据库表。这是我的桌子的样子

Lookup

1
2
3
4
5
6
+--------+--------------+------------+
| Column |   DataType   | Attributes |
+--------+--------------+------------+
| Id     | INT          | PK         |
| Code   | NVARCHAR(50) |            |
+--------+--------------+------------+

Culture

1
2
3
4
5
6
+--------------+--------------+------------+
|    Column    |   DataType   | Attributes |
+--------------+--------------+------------+
| Id           | INT          | PK         |
| Culture_Code | NVARCHAR(10) |            |
+--------------+--------------+------------+

Lookup_t9n

1
2
3
4
5
6
7
+----------------+---------------+---------------------+
|     Column     |   DataType    |     Attributes      |
+----------------+---------------+---------------------+
| Id             | INT           | PK                  |
| Culture_Id     | INT           | FK to Culture table |
| Localised_Text | NVARCHAR(MAX) |                     |
+----------------+---------------+---------------------+

如您所见,我有一个查找表,其中存储了所有查找。查找的显示文本已本地化并存储在单独的表中。该表具有区域性表的外键,以指示存在本地化文本的区域性。

我的课看起来像这样

1
2
3
4
5
6
7
8
public class Lookup {

    public virtual int Id {get; set;}

    public virtual string Code {get; set;}

    public virtual string DisplayText {get; set;}
}

我的FNH映射类如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
public class LookupMappings : ClassMap<Lookup> {

    public LookupMappings()
    {
        Table("Lookup");
        Id(x => x.Id).Column("Id");
        Map(x => x.Code).Column("Code");

        Join("Lookup_t9n", join => {
            join.Map(x => x.DisplayText).Column("Localised_Text"); //Note this place, my problem is here
        })
    }
}

在上面的映射中,在Join部分中,我想提供一些WHERE Lookup_t9n.Culture_Id = Culture.Culture_Id AND Culture.Culture_Code = System.Threading.Thread.CurrentUICulture.CultureCode之类的where子句。

我知道这不是有效的SQL,但传达了我希望的意图。有没有人有做这种事情的经验。

我可以添加一个映射层,在其中可以有一些类与数据库表进行一对一映射,然后编写普通的c#将这些类映射回我的Lookup类。我宁愿将其作为临时解决方案。我想知道是否可以通过使用一些智能NH来删除该映射层。


我没有简单的答案,例如CallThis()。我想根据我们如何使用类似的东西给您建议。该解决方案基于标准映射,将其复杂性隐藏在C#实体中。这只是解决方案的草稿,因此我将跳过中间的Culture表,并期望在Lookup_t9n中我们仅存储文化名称(en,cs ...)

我们上这堂课

1
2
3
4
5
6
7
8
9
10
11
12
public class Lookup {
    public virtual int Id {get; set;}
    public virtual string Code {get; set;}
                                     // for simplicity skipping null checks    
    public virtual DisplayText { get { return Localizations.First().LocalizedText; } }
    public virtual IList<Localization> Localizations {get; set;}
}

public class Localization { // mapped to Lookup_t9n
    public virtual string CultureName {get; set;}
    public virtual string LocalizedText {get; set;}
}

有了这个,我们可以将Localizations的集合映射为HasMany。甚至可以将其映射为组件(请参阅组件映射示例)

现在,我们要做的是引入一个过滤器。流利的例子。基本文件:18.1。 NHibernate过滤器。

简化的映射

过滤:

1
2
3
4
5
6
7
public class CulturFilter : FilterDefinition
{
  public CulturFilter()
  {
    WithName("CulturFilter")
        .AddParameter("culture",NHibernate.NHibernateUtil.String);
  }

采集:

1
2
3
4
5
HasMany(x => x.Localization)
    .KeyColumn("Id")
    ...
    .ApplyFilter<CulturFilter>("CultureName = :culture"))
    .Cascade.AllDeleteOrphan();

最后,我们必须引入一些AOP过滤器IInterceptor ...,该过滤器每次都会触发(需要)并调整ISession

1
2
3
4
session
   .EnableFilter("CulturFilter")
   .SetParameter("culture"
     ,System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName);

现在,我们有了基于当前区域性的Localized字符串,同时将本地化值的标准映射用作集合。