Мне сложно настроить отображение Fluent NHibernate для моей модели.
Я моделирую простой домен, в котором у Forum
есть много Participants
, у каждого из них много Tags
.
Каждое из этих отношений представляет собой однонаправленную композицию один ко многим
Из-за этого я хотел бынастроить NHibernate для удаления Tag
после удаления ассоциации между Tag
и Participant
(т. е. тег удаляется из коллекции) при вызове ResetTags
метода
Однако при удалении Tag
из коллекции тегов в Participant
с использованием метода ResetTags
я получаю следующее исключение при совершении транзакции
NHibernate.HibernateException HResult = 0x80131500 Сообщение = Коллекция с cascade = "all-delete-orphan"больше не ссылался на экземпляр объекта-владельца: LanguageWire.Dialogues.Domain.Dialogue.Participants Source = mscorlib
Пожалуйста, дайте мне знать, что мне здесь не хватает.
Вот как выглядит сокращенный код
public class Forum : AggregateRoot
{
private IList<Participant> _participants = new List<Participant>();
public virtual IReadOnlyCollection<Participant> Participants => new ReadOnlyCollection<Participant>(_participants);
}
public class Participant : IEquatable<Participant>
{
private int _id;
private IList<Tag> _tags = new List<Tag>();
public virtual void ResetTags(params Tag[] tags)
{
if (tags == null) throw new ArgumentNullException(nameof(tags));
_tags.Clear();
foreach (var tag in tags) _tags.Add(tag);
}
}
public class Tag : IEquatable<Tag>
{
private int _id;
private byte _typeId;
private int _entityId;
}
Вот мои сопоставления
public class ForumMapping : ClassMap<Forum>
{
public ForumMapping()
{
Id(x => x.Id);
HasMany(x => x.Participants)
.Not.Inverse()
.Cascade.AllDeleteOrphan()
.BatchSize(Default.BatchSize);
}
}
public class ParticipantMapping : ClassMap<Participant>
{
public ParticipantMapping()
{
Id(x => x.Id);
HasMany(x => x.Tags)
.Cascade.AllDeleteOrphan()
.Not.Inverse()
.Not.KeyNullable()
.Not.KeyUpdate()
.BatchSize(Default.BatchSize);
Cache.ReadWrite().Region(nameof(Participant));
}
}
public class TagMapping : ClassMap<Tag>
{
public TagMapping()
{
Id(x => x.Id);
Map(x => x.EntityId)
.Not.Nullable()
.Not.Update();
Map(x => x.TypeId)
.Not.Nullable()
.Not.Update();
}
}
По соглашению сопоставления относятся к полям (не к свойствам, поэтому нет проблем с заменой NHibernateколлекция реализаций с новым экземпляром)
public ISessionFactory BootstrapSessionFactory()
{
NHibernateLogger.SetLoggersFactory(new SerilogNHibernateLoggerFactory());
return Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2012.ConnectionString(_dataAccessConfiguration.DatabaseConnectionString))
.Cache(cache => cache.UseSecondLevelCache())
.Mappings(m =>
m.FluentMappings
.AddFromAssemblyOf<PersistenceSetup>()
.Conventions.Add(
DefaultAccess.CamelCaseField(CamelCasePrefix.Underscore),
Вот как я сохраняю данные
_session.FlushMode = FlushMode.Commit;
using (var transaction = _session.BeginTransaction())
{
foreach (var aggregate in _aggregates)
await _session.SaveOrUpdateAsync(aggregate, cancellationToken);
await transaction.CommitAsync(cancellationToken);
}
Версии пакетов, которые я использую:
<PackageReference Include="FluentNHibernate" Version="2.1.2" />
<PackageReference Include="NHibernate" Version="5.1.3" />