/// <summary> /// Implements the interface. This causes the hook to only run for objects that are assignable to TEntity. /// </summary> public void HookObject(object entity, HookEntityMetadata metadata) { if (typeof(TEntity).IsAssignableFrom(entity.GetType())) { Hook((TEntity)entity, metadata); } }
/// <summary> /// Executes the pre action hooks, filtered by <paramref name="requiresValidation"/>. /// </summary> /// <param name="modifiedEntries">The modified entries to execute hooks for.</param> /// <param name="requiresValidation">if set to <c>true</c> executes hooks that require validation, otherwise executes hooks that do NOT require validation.</param> private void ExecutePreActionHooks(IEnumerable <HookedEntityEntry> modifiedEntries, bool requiresValidation) { foreach (var entityEntry in modifiedEntries) { var entry = entityEntry; //Prevents access to modified closure foreach ( var hook in PreHooks.Where(x => (x.HookStates & entry.PreSaveState) == entry.PreSaveState && x.RequiresValidation == requiresValidation)) { var metadata = new HookEntityMetadata(entityEntry.PreSaveState, this); hook.HookObject(entityEntry.Entity, metadata); if (metadata.HasStateChanged) { entityEntry.PreSaveState = metadata.State; } } } }
/// <summary> /// Saves all changes made in this context to the underlying database. /// </summary> /// <returns> /// The number of objects written to the underlying database. /// </returns> public override int SaveChanges() { var modifiedEntries = this.ChangeTracker.Entries() .Where(x => x.State != EntityState.Unchanged && x.State != EntityState.Detached) .Select(x => new HookedEntityEntry() { Entity = x.Entity, PreSaveState = x.State }) .ToArray(); ExecutePreActionHooks(modifiedEntries, false); //Regardless of validation (executing the hook possibly fixes validation errors) var hasValidationErrors = this.Configuration.ValidateOnSaveEnabled && this.ChangeTracker.Entries().Any(x => x.State != EntityState.Unchanged && !x.GetValidationResult().IsValid); var hasPostHooks = this.PostHooks.Any(); // Save this to a local variable since we're checking this again later. if (!hasValidationErrors) { ExecutePreActionHooks(modifiedEntries, true); } var result = base.SaveChanges(); if (hasPostHooks) { foreach (var entityEntry in modifiedEntries) { var entry = entityEntry; //Obtains hooks that 'listen' to one or more Entity States foreach (var hook in PostHooks.Where(x => (x.HookStates & entry.PreSaveState) == entry.PreSaveState)) { var metadata = new HookEntityMetadata(entityEntry.PreSaveState, this); hook.HookObject(entityEntry.Entity, metadata); } } } return(result); }
/// <summary> /// Executes the pre action hooks, filtered by <paramref name="requiresValidation"/>. /// </summary> /// <param name="modifiedEntries">The modified entries to execute hooks for.</param> /// <param name="requiresValidation">if set to <c>true</c> executes hooks that require validation, otherwise executes hooks that do NOT require validation.</param> private void ExecutePreActionHooks(IEnumerable<HookedEntityEntry> modifiedEntries, bool requiresValidation) { foreach (var entityEntry in modifiedEntries) { var entry = entityEntry; //Prevents access to modified closure foreach (var hook in _ctx.PreHooks.Where(x => (x.HookStates & entry.PreSaveState) == entry.PreSaveState && x.RequiresValidation == requiresValidation)) { var metadata = new HookEntityMetadata(entityEntry.PreSaveState, _ctx); hook.HookObject(entityEntry.Entity, metadata); if (metadata.HasStateChanged) { entityEntry.PreSaveState = metadata.State; } } } }
public void RunPostActionHooks() { var hasPostHooks = _ctx.PostHooks.Any(); // Save this to a local variable since we're checking this again later. if (hasPostHooks) { foreach (var entityEntry in _modifiedEntries) { var entry = entityEntry; //Obtains hooks that 'listen' to one or more Entity States foreach (var hook in _ctx.PostHooks.Where(x => (x.HookStates & entry.PreSaveState) == entry.PreSaveState)) { var metadata = new HookEntityMetadata(entityEntry.PreSaveState, _ctx); hook.HookObject(entityEntry.Entity, metadata); } } } }
private void ObjectMaterialized(object sender, ObjectMaterializedEventArgs e) { var metadata = new HookEntityMetadata(EntityState.Unchanged, this); foreach (var postLoadHook in PostLoadHooks) { postLoadHook.HookObject(e.Entity, metadata); } }
/// <summary> /// Executes the pre action hooks, filtered by <paramref name="requiresValidation"/>. /// </summary> /// <param name="modifiedEntries">The modified entries to execute hooks for.</param> /// <param name="requiresValidation">if set to <c>true</c> executes hooks that require validation, otherwise executes hooks that do NOT require validation.</param> private void ExecutePreActionHooks(IEnumerable<HookedEntityEntry> modifiedEntries, bool requiresValidation) { if (!_hooks.Any(h => h is IPreActionHook)) return; foreach (var entry in modifiedEntries) { // For each preaction hook ordered by Order where null values are last (since null means it doesn't matter what order they have) foreach ( var hook in _hooks.Where( h => h.Hook is IPreActionHook ) .Where(x => (x.Hook.HookStates & entry.PreSaveState) == entry.PreSaveState && (x.Hook as IPreActionHook).RequiresValidation == requiresValidation) .OrderByDescending( x => x.Order.HasValue ).ThenBy( x => x.Order ) ) { var metadata = new HookEntityMetadata(entry.PreSaveState, this, entry.Entry); hook.Hook.HookObject(entry.Entry.Entity, metadata); } } }
private void ExecutePostActionHooks(IEnumerable<HookedEntityEntry> modifiedEntries) { if (!_hooks.Any(h => h is IPostActionHook)) return; foreach (var entityEntry in modifiedEntries) { var entry = entityEntry; //Obtains hooks that 'listen' to one or more Entity States foreach (var hook in _hooks.Where(h => h is IPostActionHook) .Where(x => (x.Hook.HookStates & entry.PreSaveState) == entry.PreSaveState) .OrderByDescending(x => x.Order.HasValue).ThenBy(x => x.Order) ) { var metadata = new HookEntityMetadata(entry.PreSaveState, this, entry.Entry); hook.Hook.HookObject(entry.Entry.Entity, metadata); } } }
public override int SaveChanges() { bool hasValidationErrors = this.Configuration.ValidateOnSaveEnabled && this.ChangeTracker.Entries().Any(x => !x.GetValidationResult().IsValid); bool hasPostHooks = this.PostHooks.Any(); // save this to a local variable since we're checking this again later. var modifiedEntries = hasValidationErrors && !hasPostHooks ? new HookedEntityEntry[0] : this.ChangeTracker.Entries() .Where(x => x.State != EntityState.Unchanged && x.State != EntityState.Detached) .Select(x => new HookedEntityEntry() { Entity = x.Entity, PreSaveState = x.State }) .ToArray(); if (!hasValidationErrors) { foreach (var entityEntry in modifiedEntries) { foreach (var hook in PreHooks.Where(x => x.HookStates == entityEntry.PreSaveState)) { var metadata = new HookEntityMetadata(entityEntry.PreSaveState); hook.HookObject(entityEntry.Entity, metadata); if (metadata.HasStateChanged) { entityEntry.PreSaveState = metadata.State; } } } } int result = base.SaveChanges(); if (hasPostHooks) { foreach (var entityEntry in modifiedEntries) { foreach (var hook in PostHooks.Where(x => x.HookStates == entityEntry.PreSaveState)) { var metadata = new HookEntityMetadata(entityEntry.PreSaveState); hook.HookObject(entityEntry.Entity, metadata); } } } return result; }
/// <summary> /// The logic to perform per entity after the registered action gets performed. /// This gets run once per entity that has been changed. /// </summary> public abstract void Hook(TEntity entity, HookEntityMetadata metadata);
/// <summary> /// Saves all changes made in this context to the underlying database. /// </summary> /// <returns> /// The number of objects written to the underlying database. /// </returns> public override int SaveChanges() { var modifiedEntries = this.ChangeTracker.Entries() .Where(x => x.State != EntityState.Unchanged && x.State != EntityState.Detached) .Select(x => new HookedEntityEntry() { Entity = x.Entity, PreSaveState = x.State }) .ToArray(); ExecutePreActionHooks(modifiedEntries, false);//Regardless of validation (executing the hook possibly fixes validation errors) var hasValidationErrors = this.Configuration.ValidateOnSaveEnabled && this.ChangeTracker.Entries().Any(x => x.State != EntityState.Unchanged && !x.GetValidationResult().IsValid); var hasPostHooks = this.PostHooks.Any(); // Save this to a local variable since we're checking this again later. if (!hasValidationErrors) { ExecutePreActionHooks(modifiedEntries, true); } var result = base.SaveChanges(); if (hasPostHooks) { foreach (var entityEntry in modifiedEntries) { var entry = entityEntry; //Obtains hooks that 'listen' to one or more Entity States foreach (var hook in PostHooks.Where(x => (x.HookStates & entry.PreSaveState) == entry.PreSaveState)) { var metadata = new HookEntityMetadata(entityEntry.PreSaveState, this); hook.HookObject(entityEntry.Entity, metadata); } } } return result; }