4

と1つのエンティティに2台を結ぶ:NHibernateのは、私は次のようなデータ構造を持つ複合キー

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

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

だから、私は2つの結合されたテーブルで、このようなデータを持つことができます:

+----------------------------------------------------------+ 
|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再開のIDと、私が欲しい言語を述語に渡して問題なくリポジトリから私が欲しいものを得ることができますに。

しかし、私は値の挿入と更新にいくつか問題があります。

私の質問は:NHibernateが現在のエンティティのレコードを更新するのではなく、Resume_Translationテーブルにのみ新しいレコードを挿入するマッピングをどのように定義するのですか?私は私のエンティティにこれを取得し、私は変更するので、もし

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

が参加し、テーブル間の一から一の関係のために良いです:私は、データベースに次のレコードを持っている場合

だから私が達成したいことはあります言語と翻訳、nhibernateは更新を実行しており、私はそれを理解することができます。同じIDを持つ新しいエンティティを異なる言語と翻訳で追加しようとすると、nhibernateはキーがすでに存在しているというエラーを生成し、私もそれを理解します。

確かに私は間違った経路をとっていますが、私が大切にしたいマッピングをどのように達成できるかについて、正しい解決策を教えてくれる人がいたら、大いに感謝します。

もう1つの質問は、エンティティとそのビジネスの観点からの翻訳をどのように扱いますか?

ご協力いただきありがとうございます。

トーマス

+0

こんにちはトーマスは、私は同じ質問を持っているが、私はずっとその解決策を好きではなかったです。あなたが投稿したのと同じことをやろうとしています。私の意見では、よりエレガントです。どんなことが起こる? – RMalke

答えて

2

Stefanが正しい軌道に乗っています。私は彼の提案を微調整し、双方向の関連性を持たせることで、より簡単に更新できるようになりました。このアプローチの一つの捉え方は、挿入時にResumeTranslationインスタンスのResumeプロパティを手動で割り当てて、NHibernateがResumeTranslation行にResumeテーブルキーを適切に割り当てるようにする必要があることです。だから、あなたがマッピングされている関連付けを与え、これは流暢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

1対多関係のようです。私は個人的に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として、それに応じてマップ(申し訳ありませんが、私は流暢な使用していないので、それは次のようになりますどのように私に聞かないでください)。それはあなたのデータベースモデルとまったく同じです。

関連する問題