4

我有以下数据结构:NHibernate的连接两个表为一个实体与复合键

+---------+ 
|Resume | 
+---------+ 
|Id (PK) | 
|IsActive | 
|...  | 
|..  | 
|.  | 
+---------+ 

+--------------------+ 
|Resume_Translation | 
+--------------------+ 
|ResumeId (PK, FK) | 
|Language (PK)  | 
|Title    | 
|Description   | 
|...     | 
|..     | 
|.     | 
+--------------------+ 

所以我能有这样的数据有两个连接表:

+----------------------------------------------------------+ 
|Id | IsActive | ResumeId | Language | Title | Description | 
+----------------------------------------------------------+ 
|1 | true  | 1  | 'fr'  | 'One' | 'One desc' | 
|1 | true  | 1  | 'pl'  | 'Raz' | 'Raz Opis' | 
|2 | true  | 2  | 'fr'  | 'B' | 'bla bla' | 
|3 | true  | 3  | 'fr'  | 'C' | 'C bla bla' | 
+----------------------------------------------------------+ 

从我的域名观点我只关心Resume实体。我不想让Resume实体收集Resume_Translations,因为我只有一个Resume实体进行当前翻译。

public class Resume 
{ 
    public virtual int Id{ get; protected internal set; } 

    public virtual string Language { get; protected internal set; } 

    public virtual string Title { get; protected internal set; } 

    public virtual string Description { get; protected internal set; } 

    public virtual bool IsActive { get; protected internal set; } 
} 

我用流利的NHibernate当前映射如下:

public class ResumeMap : ClassMap<Resume> 
{ 

    public ResumeMap() 
    { 
     Table("Resume"); 
     Id(x => x.Id); 
     Map(x => x.IsActive); 
     // other properties 
     Join("Resume_Translation", m => 
         { 
          m.Fetch.Join(); 
          m.Map(x => x.Language).Length(5); 
          m.Map(x => x.Title).Length(100); 
          m.Map(x => x.Description).Length(200); 
         }); 
    } 
} 

我能得到什么,我从资料库要没有问题只是路过在简历的WHERE谓词的标识,我想语言至。

但是,我插入和更新值有一些问题。

我的问题是:我如何定义一个映射,NHibernate插入一个新的记录只在Resume_Translation表中而不是更新当前实体的记录?

所以我想实现的是,如果我有在数据库中有如下记载:

|2 | true  | 2  | 'fr'  | 'B' | 'bla bla' | 

加入有利于表之间一对一的关系,所以如果我得到这个在我的实体,我改变语言和翻译,nhibernate正在执行更新,我可以理解它。如果我尝试通过不同的语言和翻译添加具有相同标识的新实体,则nhibernate会产生一个错误,即某个键已经存在,我也理解它。

所以,当然我会走错路,但如果有人能指出我正确的解决方案,我如何能够实现我想要的映射,我将不胜感激。

另一个问题,你如何从商业角度处理实体和他们的翻译?

非常感谢您的帮助。

Thomas

+0

嗨托马斯,我有同样的问题,但我不喜欢那个解决方案。我正在尝试做与你发布的相同的内容,并且在我看来这更公平更优雅。任何与此? – RMalke

回答

2

Stefan走上正轨。我已经调整了他的建议,使双向关联可以使更新更容易。使用这种方法的一个问题是,在插入时需要手动指定ResumeTranslation实例的Resume属性,这样NHibernate才能将Resume表键正确地分配给ResumeTranslation行。所以,鉴于你正在映射的关联,这就是它在Fluent NH中的外观:

public class ResumeTranslation 
{ 
    public virtual string Title { get; protected internal set; } 

    public virtual string Description { get; protected internal set; } 

      //Needed for bi-directional association: 
    public virtual Resume Resume { get; set; } 
} 


public class ResumeTranslationMap : ClassMap<ResumeTranslation> 
{ 

    public ResumeTranslationMap() 
    { 
     Table("ResumeTranslation"); 
     CompositeId() 
      .KeyReference(kp => kp.Resume, "ResumeId") 
      .KeyProperty(kp => kp.Language, "Language"); 

     Map(x => x.Title); 
     Map(x => x.Description); 
    } 
} 

public class ResumeMap : ClassMap<Resume> 
{ 

    public ResumeMap() 
    { 
     Table("Resume"); 
     Id(x => x.Id); 
     Map(x => x.IsActive); 
     // other properties 

     HasMany(c => c.Translations) 
      .Inverse() 
      .KeyColumn("id") //May not be required but here for reference 
      .Cascade.All(); 
    } 
} 
2

看起来像是一对多的关系。我会亲自收集ResumeTranslation对象在我的简历对象中。然后我会把它作为一个标准映射到许多。

然后,您可以ActiveResumeTranslation添加其他属性,以你的简历实体能够代表您current translation的。

+0

+1我会以同样的方式 – Firo

+0

这就是说,ResumeTranslation从我的观点来看没有任何意义。这就是为什么这个问题;) –

2

如何使用字典,使用该语言作为关键?

public class ResumeTranslation 
{ 
    public virtual string Title { get; protected internal set; } 

    public virtual string Description { get; protected internal set; } 
} 

public class Resume 
{ 
    public virtual int Id{ get; protected internal set; } 

    // language is the key to the translation 
    // you may even want to hide the dictionary from the public interface of 
    // this class and only provide access to a "current" language. 
    public virtual IDictionary<string, ResumeTranslation> Translations { get; private set; } 

    public virtual bool IsActive { get; protected internal set; } 
} 

并据此绘制它作为一个复合元素的map(对不起,我没有使用流畅,所以不要问我它会是什么样子)。它完全符合你的数据库模型。

相关问题