Как настроить мою коллекцию как недоступную только для чтения с помощью FluentNhibernate?
Я перепробовал все, что мог придумать, и я просто застрял. у меня есть User
это имеет много Invitations
но когда я пытаюсь добавить Invitation
к invitations
поле User
позвонив AddInvitation()
NotSupported
исключение выбрасывается, потому что Collection is 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
}
У меня есть фактическое сообщение об исключении (должен был добавить это изначально)
в System.ThrowHelper.ThrowNotSupportedException(ресурс ExceptionResource) в System.Collections.ObjectModel.ReadOnlyCollection'1.System.Collections.Generic.ICollection.Add(значение T) в NHibernate.Collection.Generic.Pagistent'enericBB.ICollection.Add(T item)
Кажется, что, хотя я изменяю приглашения к полям, оболочка ReadOnlyCollection, добавляемая приглашениями доступа, изменяет само поле.
2 ответа
Я думаю, что проблема исходит от ReadOnlyCollection. Есть ли какая-то причина, по которой вы инициализируете приглашения только для чтения?
В вашем отображении вы заполняете данные в коллекцию "Приглашение только для чтения" и, возможно, ваша инициализация поля приглашения в виде "Список" скрывается коллекцией только для чтения.
Возможно, попробуйте не переинициализировать коллекцию приглашений каждый раз, когда вы хотите получить доступ, а просто вернуть поле приглашений, вы можете сделать это поле доступным только для чтения.
Старый вопрос, актуальная проблема! И это не так сложно исправить, сохраняя коллекцию только для чтения:
userMapping.HasMany<Invitation>(userType => userType.Invitations)
.Not.LazyLoad()
.Inverse()
.Access.CamelCaseField() // this does the trick!
.Cascade.SaveUpdate()
.KeyColumn("User_id");
Если NHibernate получает доступ к коллекции через вспомогательное поле, он не знает, что она доступна только для чтения, поэтому он будет создавать экземпляр коллекции для чтения и записи. Публичный интерфейс остается доступным только для чтения.