NHibernate: Обновление коллекций во время EventListener «PreUpdateEvent»

Я пытаюсь написать отслеживание аудита для Nhibernate, которое подключается к событию PreUpdate. У меня есть AuditLogEntry класс (когда, кто и т. д.), который содержит список AuditLogEntryDetails (т. е. отдельные измененные свойства). Если я изолирую класс AuditLogEntry от проверяемой сущности, мой код будет работать без ошибок. Однако, если я добавлю список AuditLogEntry для проверяемой сущности, тогда мой код создает

коллекцию [DomainObjects.AuditTracking.AuditLogEntry.Details], которая не была обработана Ошибка утверждения flush ()

при попытке сохранить измененный список в прослушивателе событий. Это происходит только тогда, когда проверяемый элемент уже имеет один (или несколько) экземпляров AuditLogEntry в списке. Если записей нет, то создается новый список, который добавляется к проверяемой сущности, и это нормально.

Я думаю, что если изолировать проблему от вышеизложенного, это будет похоже на (ленивую) загрузку существующего списка, чтобы добавить новый экземпляр AuditLogEntry. Однако я не смог продвинуться дальше. Добавление 'Lazy = "False"' в сопоставление списка не помогает. Я действительно нахожусь на первых этапах использования NHibernate, позаимствовав концепции как из Поваренной книги HN 3.0, так и из этого сообщения в блоге . Мой код очень похож на этот, Строки, вызывающие проблему, закомментированы ближе к концу блока кода

    public void TrackPreUpdate(IAuditTrackedEntity entity, object[] oldState, object[] state, IEntityPersister persister, IEventSource eventSource)
    {
        if (entity == null || entity is AuditLogEntry)
            return;

        var entityFullName = entity.GetType().FullName;
        if (oldState == null)
        {
            throw new ArgumentNullException("No old state available for entity type '" + entityFullName +
                                            "'. Make sure you're loading it into Session before modifying and saving it.");
        }

        var dirtyFieldIndexes = persister.FindDirty(state, oldState, entity, eventSource);
        var session = eventSource.GetSession(EntityMode.Poco);

        AuditLogEntry auditLogEntry = null;
        foreach (var dirtyFieldIndex in dirtyFieldIndexes)
        {
            if (IsIngoredProperty(persister, dirtyFieldIndex))
                continue;

            var oldValue = GetStringValueFromStateArray(oldState, dirtyFieldIndex);
            var newValue = GetStringValueFromStateArray(state, dirtyFieldIndex);

            if (oldValue == newValue)
            {
                continue;
            }
            if (auditLogEntry == null)
            {
                auditLogEntry = new AuditLogEntry
                                    {
                                        AuditEntryType = AuditEntryTypeEnum.Update,
                                        EntityShortName = entity.GetType().Name,
                                        EntityFullName = entityFullName,
                                        Username = Environment.UserName,
                                        //EntityId = entity.Id,
                                        When = DateTime.Now,
                                        Details =  new List()
                                    };


                //**********************
                // The next three lines cause a problem when included,
                // collection [] was not processed by flush()
                //**********************
                if (entity.ChangeHistory == null)
                    entity.ChangeHistory = new List();
                entity.ChangeHistory.Add(auditLogEntry);

                session.Save(auditLogEntry);    
            }

            var detail = new AuditLogEntryDetail  
                             {
                                 //AuditLogEntryId = auditLogEntry.Id,
                                 PropertyName = persister.PropertyNames[dirtyFieldIndex],
                                 OldValue = oldValue,
                                 NewValue = newValue
                             };
            session.Save(detail);
            auditLogEntry.Details.Add(detail);

        }

        session.Flush();
    }

Как было сказано ранее, в этой конфигурации я получаю ошибку подтверждения " collection [] не был обработан flush () ". Если я удалю три строки выше и отображение списка в lookupcode.hmb.xml, тогда все будет работать, как ожидалось, кроме проверяемой сущности больше не будет содержать ссылки на собственные проверяемые элементы.

8
задан Paul Hadfield 3 December 2010 в 13:42
поделиться