4

次のような双方向の関連付けがあります。

public class Parent
{
  public int ParentId {get; set;}
  ...other properties
  public IEnumerable<Child> Children {get; set;}
}

public class Child
{
  public int ChildId {get; set;}
  ...other properties
  public Parent Parent {get; set;}
}

流暢なマッピングは次のとおりです。

親マッピング

Id(x => x.ParentId, "PARENT_ID").GeneratedBy.Identity();
.. other mappings
HasMany(x => x.Children).Cascade.All().KeyColumn("PARENT_ID");

子マッピング

Id(x => x.ChildId, "CHILD_ID").GeneratedBy.Identity();
.. other mappings
References(x => x.Parent).Column("PARENT_ID").Cascade.None();

次のようなコードを実行すると:

Parent parent = new Parent{ ..set some properties... };
parent.Children = new[] { new Child{ ..set some properties.. };
session.Save(parent);

PARENT_IDNHibernateが子レコードを挿入しようとしたときに子レコードの列を新しい ID に設定していないため、外部キー制約違反が発生します。

のマッピングでカスケードを要求したことは明らかですParent。NHibernate は子を保存しようとしていますが、ID が設定されていないのはなぜですか?

4

1 に答える 1

7

2 つの変更を行う必要があります。

  1. が必要.Inverse()ですHasMany(x => x.Children)。詳細については、逆を説明する私の回答を参照してください。
  2. child.Parent = parent;エンティティを保存するコードにも追加する必要があります。

あなたの場合、2 つの関係は互いに競合しています。 parent.Childrenこれはchild、NHibernate がChild.PARENT_ID親の Id として存続する必要がchild.Parentあることを意味しますが、null です。NHibernate がChild.PARENT_IDnull として存続する必要があることを意味します。どうやらchild.Parent勝った。実際には、どちらも勝った可能性が高いです。NHibernate は、おそらくこれらに似た 2 つのクエリを実行していました...

/* This is what child.Parent says we should save.
   This query will fail because PARENT_ID is NOT NULL. */
insert into Child (CHILD_ID, PARENT_ID) values (@childId, null);

/* This is what parent.Children says we should save. */
update Child set PARENT_ID = @parentId where CHILD_ID = @childId;

上記で推奨する 2 つの変更を行うと、NHibernate は次のようにこれを正しく保存できます。

insert into Child (CHILD_ID, PARENT_ID) values (@childId, @parentId);
于 2013-08-22T17:36:56.207 に答える