2010-12-16 12 views
18

私は以下のように関係を設定しようとしています。単方向の1対多の関係のNHibernateの設定

public class Detail { 
    public virtual Guid DetailId { get; set; } 
    public virtual string Name { get; set; } 
} 
public class Master { 
    public virtual Guid MasterId { get; set; } 
    public virtual string Name { get; set; } 
    public virtual IList<Detail> Details { get; set; } 
} 

とマッピング:各マスターアイテムが1つまたは複数の詳細項目がある

public class MasterMap : ClassMap<Master> 
{ 
    public MasterMap() 
    { 
     Id(x => x.MasterId); 
     Map(x => x.Name); 
     HasMany(x => x.Details).Not.KeyNullable.Cascade.All(); 
    } 
} 
public class DetailMap : ClassMap<Detail> 
{ 
    public DetailMap() 
    { 
     Id(x => x.Id); 
     Map(x => x.Name); 
    } 
} 

マスターデータベーステーブルがある:

masterId uniqueidentifier NOT NULL 
name  nvarchar(max) NULL 

詳細

DetailId uniqueidentifier NOT NULL 
name  nvarchar(max) NULL 
MasterId uniqueidentifier NULL 
foreign key (masterId) references [Master] 

私は本当に戻ってマスターへのディテールからのリンクを持っている気にしない - 言い換えれば、自分で詳細オブジェクトは、ちょうど私のドメイン層に面白いではありません。 は常ににMasterオブジェクト経由でアクセスします。これはthis postに概説狂気の制限を除いて、素晴らしい作品

Master mast = new Master 
{ 
    MasterId = new Guid(), 
    Name = "test", 
    Details = new List<Detail> 
    { 
     new Detail { .DetailId = new Guid(), .Name = "Test1" }, 
     new Detail { .DetailId = new Guid(), .Name = "Test1" } 
    } 
}; 

using (transaction == Session.BeginTransaction) 
{ 
    Session.Save(mast); 
    transaction.Commit(); 
} 

:NHibernateのは、INSERTを行い、最初のNULLとしてDetail.MasterIdを置き、その後にそれを設定するUPDATEを行い、このようなコードを使用して

本当のMasterId。

実際には、NULL MasterIdのディテールエントリーを望んでいないので、MasterIdフィールドをNOT NULLに設定すると、NHibernateがMasterId = NULLを入れようとしているので、DetailへのINSERTは失敗します。

私は私の質問はこれに沸く推測:私は上記のコードサンプルは、(Detail.Masterプロパティを追加することなく、例えば、)私の既存のドメインモデルで動作するように取得できますか

、およびDetail.MasterIdフィールドデータベースでNOT NULLに設定されていますか?

Nhibernateに、後でUPDATEを実行するのではなく、最初のINSERTに正しいMasterIdを入れるだけの方法はありますか?この意思決定のどこかに根拠がありますか? - なぜこのようにするのか苦労しています。

答えて

14

できません。

非常に重要な注意:あなたがにリンクされている他の質問にmy answerからリンクを引用すると、作成または更新するとき<one-to-many>協会の<key>列がNOT NULLと宣言されている場合は、NHibernateのは、制約違反を引き起こす可能性があり協会。この問題を回避するには、inverse="true"とマークされた多くの値のある端(セットまたはバッグ)との双方向の関連付けを使用する必要があります。この章で後述する双方向の関連付けの説明を参照してください。

編集:Hazzikが正しく指摘しているように、これは上記NHibernateは3とに変更されました。[あなたがいる場合]、<key>にNH3をinverse="false"not-nullを設定し、上記のインサートインサート更新のINSEAD 2つだけ挿入を実行します

:ドキュメントは、悲しいことにそうここHazzikだ、更新されていません。

+0

私はそれを読んでいないんでしたが、それは本当に何も説明していません(どちらも参照双方向関連の議論を行います)。この決定の背後には論理的根拠がありますか?それはnhibernateの設計上の制限ですか?バグですか?比較的初心者で、内部を全く知らないので、これが可能であるようです。 – gregmac

+0

正直なところ、私は分かりません。それはNHibernateチームによってバグとして分類されません、それはNHibernateがどのようにエンティティを持続させるかの副作用です。私はその理由を知っているようなふりをするつもりはないが、データベースとアイデンティティジェネレーターにとらわれないこととは関係があると思う。 –

+4

実際にキーNH3の逆=「false」をと非NULLに設定し、上記のインサートインサート更新 – hazzik

4

この方法があるNHibernateのは、それをしない理由理由:
それが唯一のディテールが知っているものを知っているの詳細を保存します。したがって、バックグラウンドで発生するマスター参照は無視されます。 マスタが保存されている場合のみ、リレーションが表示され、コレクションの要素がマスタのIDで更新されます。
オブジェクト指向の視点からの論理です。しかし、保存の視点からは、やや論理的ではありません。私はあなたがいつもバグ報告を書いたり、既に提出されているかどうかを見て、それを変更するように依頼することができると思います。しかし、彼らは彼らの特定の(設計/ドメイン)理由があると思います。

31

NH3と上記迷惑save nullせずに単方向の1対多マッピングの場合、エンティティを保存し修正することができます - あなたは< 1対上not-null="true" <上のキー>とinverse="false"の両方を設定した場合、updateサイクル - saveそのため、多くの>

FluentNHibernateコードスニペットは:

public class MasterMap : ClassMap<Master> 
{ 
    public MasterMap() 
    { 
     Id(x => x.MasterId); 
     Map(x => x.Name); 
     HasMany(x => x.Details) 
      .Not.Inverse()  //these options are very 
      .Not.KeyNullable() //important and work only if set together 
      .Not.KeyUpdate() //to prevent double update 
      .Cascade.All(); 
    } 
} 
+1

繰り返し更新は行われませんか?私は、アウトラインでマッピングを設定し、外部キーを正しく挿入する(nullを挿入するのではなく)が、外部キーを挿入時に使用したのと同じ値にリセットする追加のデータベース更新を行います。 VikciaRが経験しているように見え、カップルの他の人たち(upvotesに基づく)も同じことを経験しています。 – Sam

+3

@Samも設定 '.Not.KeyUpdate()'とダブル更新が期待通り – hazzik

+1

クエリは動作しますが、NHibernateのはまだnull入力可能値を許可するデシベルに列を作成してしまっでしょうか?これは正常ですか? – nemenos

関連する問題