I've tried everything I can think of here and I'm just stuck. I have a User
that has many Invitations
but when I try to add an Invitation
to the invitations
field of the User
by calling AddInvitation()
a NotSupported
exception is thrown because the Collection is read-only
. I get the feeling that it's something in the mapping overrides but I have various other classes / relationships following the same pattern and (so far) I don't get this issue elsewhere. Why is the backing field read-only and what should I be doing to prevent the backing field becoming read-only?
User.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;
}
}
Invitation.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;
}
}
Database.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
}
I've got the actual exception message (should have added this initially)
at System.ThrowHelper.ThrowNotSupportedException(ExceptionResource resource) at System.Collections.ObjectModel.ReadOnlyCollection'1.System.Collections.Generic.ICollection.Add(T value) at NHibernate.Collection.Generic.PersistentGenericBag'1.System.Collections.Generic.ICollection.Add(T item)
It seems that even though I'm modifying the field invitations the ReadOnlyCollection wrapper added by the accessor Invitations is modifying the field itself.
I think that the problem is coming from ReadOnlyCollection, is there any reasony why you are initializing Invitations as read-only collection?
In your mapping your are populating data into Invitation read-only colleciton and maybe your initialization of invitation field as List is hide by read-only collection.
Maybe try to not re-initialize collection of invitations every time when you want to access, but just return invitations field, you can make this field as read-only.