NHibernate Cascade AllDeleteOrphan не работает для однонаправленной ассоциации - PullRequest
0 голосов
/ 01 октября 2018

Мне сложно настроить отображение Fluent NHibernate для моей модели.

Я моделирую простой домен, в котором у Forum есть много Participants, у каждого из них много Tags.
Каждое из этих отношений представляет собой однонаправленную композицию один ко многим enter image description here

Из-за этого я хотел бынастроить 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" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...