1

ここで考えられることはすべて試しましたが、行き詰まっています。多くUserの がありますが、を呼び出してのフィールドにInvitationsを追加しようとすると、. マッピングのオーバーライドに何かあるような気がしますが、同じパターンに従って他のさまざまなクラス/関係があり、(これまでのところ)この問題は他の場所では発生していません。バッキング フィールドが読み取り専用である理由と、バッキング フィールドが読み取り専用にならないようにするにはどうすればよいですか?InvitationinvitationsUserAddInvitation()NotSupportedCollection is read-only

ユーザー.cs

public class User
{
  private IList<Invitation> invitations = new List<Invitation>();

  public virtual IEnumerable<Invitation> Invitations
  {
    get { return new ReadOnlyCollection<Invitation>(this.invitations);
  }

  public virtual User AddInvitation(Invitation invitation)
  {
    if (!this.invitations.Contains(invitation))
    {
      this.invitations.Add(invitation); // <-- throws System.NotSupportedException: Collection is read-only.
    }

    return this;
  }
}

招待.cs

public class Invitation
{
  private User sender = null;

  public virtual User Sender
  {
    get { return this.sender; }
  }

  public virtual Invitation From(User sender)
  {
    this.sender = sender;
    return this;
  }
}

データベース.cs

public class Database
{
  // code removed for brevity
  private static void MapAssemblies(FluentNHibernate.Cfg.MappingConfiguration config)
  {
    config.AutoMappings.Add(
      AutoMap.Assembly(Assembly.GetAssembly(typeof(User)))
      .Override<User>(userMapping =>
      {
        userMapping.HasMany<Invitation>(userType => userType.Invitations)
        .Not.LazyLoad()
        .Inverse()
        .Cascade.SaveUpdate()
        .KeyColumn("User_id");
      })
      .Override<Invitation>(invitationMapping =>
      {
        invitationMapping.References<User>(invitationType => invitationType.Sender)
        .Column("User_id");
      });
    );
  }
  // code removed for brevity
}

Manager.cs

public class Manager
{
  private ISession session = null; // initialised in .ctor

  // code removed for brevity
  public void AddInvitation(/*parameters removed*/)
  {
    User user = this.session.Get<User>(identifier);
    Invitation invitation = new Invitation().From(user);
    user.AddInvitation(invitation);
    using (ITransaction transaction = this.session.BeginTransaction())
    {
      this.session.SaveOrUpdate(invitation);
      transaction.Commit();
    }
  }
  // code removed for brevity
}

実際の例外メッセージを取得しました (最初にこれを追加する必要がありました)

System.ThrowHelper.ThrowNotSupportedException (ExceptionResource リソース) で System.Collections.ObjectModel.ReadOnlyCollection'1.System.Collections.Generic.ICollection.Add(T 値) で NHibernate.Collection.Generic.PersistentGenericBag'1.System.Collections.Generic .ICollection.Add(T アイテム)

フィールドの招待状を変更しているにもかかわらず、アクセサー Invitations によって追加された ReadOnlyCollection ラッパーがフィールド自体を変更しているようです。

4

2 に答える 2

1

問題はReadOnlyCollectionにあると思いますが、Invitationsを読み取り専用コレクションとして初期化する理由はありますか?

マッピングでは、データをInvitation読み取り専用コレクションに入力し、リストとしての招待フィールドの初期化は読み取り専用コレクションによって非表示になっている可能性があります。

アクセスするたびに招待状のコレクションを再初期化するのではなく、招待状フィールドを返すだけで、このフィールドを読み取り専用にすることができます。

于 2012-10-18T13:48:40.713 に答える
0

古い質問、実際の問題! コレクションを読み取り専用のままにしておくと、修正するのはそれほど難しくありません。

    userMapping.HasMany<Invitation>(userType => userType.Invitations)
    .Not.LazyLoad()
    .Inverse()
    .Access.CamelCaseField() // this does the trick!
    .Cascade.SaveUpdate()
    .KeyColumn("User_id");

NHibernate がバッキング フィールドを介してコレクションにアクセスする場合、それが読み取り専用であることを認識しないため、読み取り/書き込みコレクションをインスタンス化します。パブリック インターフェイスは読み取り専用のままです。

于 2016-07-29T06:02:42.843 に答える