11

I have a very simple unidirectional mappings. see below:

    public ContactMap()
    {
        Id(x => x.Id).GeneratedBy.Assigned();
        Map(x => x.Name);
        References(x => x.Device);
        HasMany(x => x.Numbers)
            .Not.Inverse()
            .Not.KeyNullable()
            .Cascade.AllDeleteOrphan()
            .Not.LazyLoad()
            .Fetch.Subselect();
        Table("Contacts");
    }


    public PhoneNumberMap()
    {
        Id(x => x.Id).GeneratedBy.Native();
        Map(x => x.Number);
        Table("ContactNumbers");
    }

According to this post after nhibernate 3 and above, setting key as non-nullable should fix the insert-update issue (The issue when NHibernate issues an insert with foreign key set to null and then an update to update the foreign key to correct value), but this is not the case for me. When I set the key as not nullable, NHibernate issues a correct insert statement

INSERT INTO ContactNumbers
            (Number,
             ContactId)
VALUES      ('(212) 121-212' /* @p0 */,
             10 /* @p1 */);

As you can see, it inserts ContactId field, but after that, it still issues update statement

UPDATE ContactNumbers
SET    ContactId = 10 /* @p0 */
WHERE  Id = 34 /* @p1 */

So to clarify the problem. NHibernate inserts Contact row with foreign key assigned correctly and after that, it issues an update statement to update the foreign key (ContactId) which is redundant.

How can I get rid of this redundant update statement? Thanks.

BTW, I'm using latest version of NHibernate and Fluent NHibernate. The database is SQLite

4

5 に答える 5

25

"updatable"=false更新を防ぐには、キーを設定する必要があります。

public ContactMap()
{
    Id(x => x.Id).GeneratedBy.Assigned();
    Map(x => x.Name);
    References(x => x.Device);
    HasMany(x => x.Numbers)
        .Not.Inverse()
        .Not.KeyNullable()
        .Not.KeyUpdate() // HERE IT IS
        .Cascade.AllDeleteOrphan()
        .Not.LazyLoad()
        .Fetch.Subselect();
    Table("Contacts");
}
于 2012-07-20T08:55:10.637 に答える
4

3.2.0ベータ版ではできません。

v3.2.0 BETAでは、1対多の改善により、この異常が一方向の1対多の関係に導入されました(実際、異常がこれと呼ばれるものであるかどうかはわかりません)。

3.2より前では、このタイプの関係が機能するためにnullを許可するように外部キーを設定する必要がありました。だから私はこれが起こるという事実を無視して、それと一緒に行きます。それ以外の場合は、完全に双方向の関係に変更する必要があります。

  • [NH-941]-1つ-多くの場合、NULL可能外部キーが必要です

リリースノートまたはJIRAの問題

編集また、あなたが指摘する投稿への答えはsave null-save-update、追加の更新を修正するのではなく、修正することです

于 2012-07-13T11:54:49.757 に答える
3

あなたが本当にそれを取り除くことができるかどうかはわかりません。

別のIDジェネレーターをネイティブとして使用してみてください。これにより、NHはIDを取得するためだけにレコードを挿入します。IDはセッション内のすべてのエンティティに使用されるため、後で挿入を行うことはできません。その後の更新の場合があります。hi-loなどを使用してください。

編集

この場合、なぜコンポーネントを使用しないのですか?電話番号が番号のみで構成されている場合は、電話番号を個別にマッピングする必要はありません。このようなもの(私はFNHユーザーではないので、間違っている可能性があります):

 public ContactMap()
 {
    Id(x => x.Id).GeneratedBy.Assigned();
    Map(x => x.Name);
    References(x => x.Device);
    HasMany(x => x.Numbers)
        .Not.Inverse()
        .Not.KeyNullable()
        .Cascade.AllDeleteOrphan()
        .Not.LazyLoad()
        .Fetch.Subselect()
        .Component(c =>
        {
          Map(x => x.Number);
        })
        .Table("ContactNumbers");
    Table("Contacts");
}
于 2012-07-13T11:54:34.097 に答える
3

マッピングでに設定inversetrue、コードで関係を割り当ててみてください。

Inverse子が親のIDを保持する責任があることを意味します。

例えば

var contact = new Contact();
var phoneNumber = new PhoneNumber();
phoneNumber.Contact = contact;

そうすれば、PhoneNumberレコードの挿入を行うときに、NHは個別の更新を行うことなくContactIdを挿入できます。

これは私がNH2で行っていたものであり、動作は3でも同じように機能すると思います。

于 2012-07-13T13:13:22.413 に答える
1

それはトレバー・ピリーが言ったことです。を使用しinverse="true"ます。持っていないことを選択した場合inverse="true"、これはその選択の結果です。あなたはそれを両方の方法で持つことはできません。

于 2012-07-17T12:49:43.877 に答える