4

次のシナリオを考えてみましょう: ユーザーはスパイスのコレクションを持っており、各スパイスは「在庫あり」または「品切れ」のいずれかになります (ブール値の RunOut プロパティで示されます)。

このようなコンポーネントを使用して、この関係を FluentNHibernate とマッピングしました

public UserMappings()
{
   Id(x => x.Id);
   Map(x => x.FirstName);
   Map(x => x.LastName);
   Map(x => x.Email).Length(255).Unique();
   HasOne(x => x.Credentials).Cascade.SaveUpdate().Fetch.Select();
   HasMany(x => x.Spices)
      .Component(c =>
          {
              c.Map(x => x.RunOut);
              c.References(x => x.BaseSpice).Fetch.Join();
          }).Table("User_Spices").Fetch.Join();

}

上記のマッピングの「Spices」コレクションは、UserSpice クラス (値オブジェクト) に対するものです。

public class UserSpice
{
    public virtual Spice BaseSpice { get; protected set; }
    public virtual bool RunOut { get; protected set; }

    public static UserSpice Create(Spice baseSpice, bool runOut)
    {
        var userSpice = new UserSpice {BaseSpice = baseSpice, RunOut = runOut};
        return userSpice;
    }
}

これは「問題なく」動作しますが、いずれかのコンポーネントを更新すると (たとえば、スパイスを RunOut = true に変更すると)、すべてのユーザーのスパイスが削除され、再挿入されます。

NHibernate には、どのユーザー スパイス参照を更新する必要があるかを一意に識別する方法がないため、これが発生していることは理解しています。

この削除と再挿入の動作を回避するために、これを別の方法でモデル化するにはどうすればよいですか?

4

2 に答える 2

3

Hibernate にはさまざまなタイプのコレクションがあります。それらのいくつかは、<list>またはのようなより複雑なマッピングから利益を得てい<idbag>ます。コレクション型の問題に関するドキュメントのこの部分をお読みください。

http://nhibernate.info/doc/nh/en/index.html#performance-collections-mostefficientupdate

短い抜粋

おそらく、インデックス付きコレクションには、値の多対多の関連付けまたはコレクションのセットよりも優れた利点がもう 1 つあります。ISet の構造により、NHibernate は要素が「変更」されたときに行を更新しません。ISet への変更は、常に (個々の行の) INSERT および DELETE を介して機能します。繰り返しますが、この考慮事項は 1 対多の関連付けには当てはまりません。

したがって、インデックス付きリスト (または idbag) を使用する場合、NHibernate はどのコレクション項目が変更されたかを理解し、UDPATE を呼び出すことさえできます。

また、インデックス付きリストをマップする方法を見つけることができる別の質問があります

Fluent Nhibernate - リストをマッピングすると NullReferenceException になりますか?

短い要約:

HasMany(x => x.MyChildren).AsList(x => x.Column("序数")).KeyColumn("AId").Not.KeyNullable();

于 2012-11-14T09:25:00.307 に答える
1

UserSpice に Equals/GetHashcode を一意性のビジネス ルール (BaseSpice の等価性と加算など) で実装.AsSet()HasMany(x => x.Spices)ます。Spices のデータ型はICollection<>or Iesi.Collections.Generic.ISet<>or にする必要がありますが、少し手間 System.Collection.Generic.ISet<>がかかります。

于 2012-11-14T09:12:01.273 に答える