Я пытаюсь написать отслеживание аудита для 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, тогда все будет работать, как ожидалось, кроме проверяемой сущности больше не будет содержать ссылки на собственные проверяемые элементы.