J'ai un écouteur d'événements (pour les journaux d'audit) qui doit ajouter les entrées du journal d'audit à l'association de l'objet:Ajouter des objets à l'association à OnPreInsert, OnPreUpdate
public Company : IAuditable {
// Other stuff removed for bravety
IAuditLog IAuditable.CreateEntry() {
var entry = new CompanyAudit();
this.auditLogs.Add(entry);
return entry;
}
public virtual IEnumerable<CompanyAudit> AuditLogs {
get { return this.auditLogs }
}
}
La collection AuditLogs
est mis en correspondance avec en cascade:
public class CompanyMap : ClassMap<Company> {
public CompanyMap() {
// Id and others removed fro bravety
HasMany(x => x.AuditLogs).AsSet()
.LazyLoad()
.Access.ReadOnlyPropertyThroughCamelCaseField()
.Cascade.All();
}
}
Et l'auditeur demande simplement l'objet auditable pour créer les entrées du journal afin qu'il puisse les mettre à jour:
internal class AuditEventListener : IPreInsertEventListener, IPreUpdateEventListener {
public bool OnPreUpdate(PreUpdateEvent ev) {
var audit = ev.Entity as IAuditable;
if (audit == null)
return false;
Log(audit);
return false;
}
public bool OnPreInsert(PreInsertEvent ev) {
var audit = ev.Entity as IAuditable;
if (audit == null)
return false;
Log(audit);
return false;
}
private static void Log(IAuditable auditable) {
var entry = auditable.CreateAuditEntry(); // Doing this for every auditable property
entry.CreatedAt = DateTime.Now;
entry.Who = GetCurrentUser(); // Might potentially execute a query as it links current user with log entry
// Also other information is set for entry here
}
}
Le problème avec c'est bien qu'il jette TransientObjectException
quand commiting la transaction:
NHibernate.TransientObjectException : object references an unsaved transient instance - save the transient instance before flushing. Type: CompanyAudit, Entity: CompanyAudit
at NHibernate.Engine.ForeignKeys.GetEntityIdentifierIfNotUnsaved(String entityName, Object entity, ISessionImplementor session)
at NHibernate.Type.EntityType.GetIdentifier(Object value, ISessionImplementor session)
at NHibernate.Type.ManyToOneType.NullSafeSet(IDbCommand st, Object value, Int32 index, Boolean[] settable, ISessionImplementor session)
at NHibernate.Persister.Collection.AbstractCollectionPersister.WriteElement(IDbCommand st, Object elt, Int32 i, ISessionImplementor session)
at NHibernate.Persister.Collection.AbstractCollectionPersister.PerformInsert(Object ownerId, IPersistentCollection collection, IExpectation expectation, Object entry, Int32 index, Boolean useBatch, Boolean callable, ISessionImplementor session)
at NHibernate.Persister.Collection.AbstractCollectionPersister.Recreate(IPersistentCollection collection, Object id, ISessionImplementor session)
at NHibernate.Action.CollectionRecreateAction.Execute()
at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
Comme le en cascade est réglé sur tous Je m'y attendais NH gérer cela. J'ai également essayé de modifier la collection en utilisant state
mais à peu près la même chose arrive.
Donc, la question est quelle est la dernière chance de modifier les associations d'objets avant qu'il ne soit sauvegardé?
Merci,
Dmitriy.
J'ai essayé cela sans succès. Ma solution était d'utiliser l'Interceptor à l'ancienne. Avec cela je pourrais facilement implémenter 'OnFlushDirty' et' OnSave'. –
Je pense @KeithS est correct, que vous devez enregistrer l'objet d'audit dans l'événement. J'ai cependant rencontré quelques problèmes avec cette solution, la session enfant renvoyée étant marquée comme fermée. La vérification de cette condition et l'utilisation de la session principale lorsque cela est le cas semble le réparer (et semble aussi très mauvais), donc je suis toujours à la recherche d'une meilleure solution à ce problème ... – Kendrick
Voici un autre lien vers le blog d'Ayende qui pourrait vous être utile: http://ayende.com/Blog/archive/2009/08/30/avoid-soft-deletes.aspx – Kendrick