/// <summary> /// Represents the bundle operation /// </summary> protected void AdtPatientRegistrationInterceptor_Bundle(object sender, DataPersistedEventArgs <Bundle> e) { foreach (var itm in e.Data.Item.Where(o => !e.Data.ExpansionKeys.Contains(o.Key.Value)).OfType <Patient>()) { AdtPatientRegistrationInterceptor_Behavior(sender, new DataPersistedEventArgs <Patient>(itm, e.Principal)); } }
/// <summary> /// Notify inserted /// </summary> protected override void OnInserted(object sender, DataPersistedEventArgs <Bundle> evt) { foreach (var itm in evt.Data.Item.Where(i => evt.Data.FocalObjects.Contains(i.Key.Value))) { PubSubNotifyQueueEntry queueEntry = null; switch (itm.BatchOperation) { case Model.DataTypes.BatchOperationType.Auto: case Model.DataTypes.BatchOperationType.InsertOrUpdate: case Model.DataTypes.BatchOperationType.Insert: queueEntry = new PubSubNotifyQueueEntry(itm.GetType(), PubSubEventType.Create, itm); break; case Model.DataTypes.BatchOperationType.Update: queueEntry = new PubSubNotifyQueueEntry(itm.GetType(), PubSubEventType.Update, itm); break; case Model.DataTypes.BatchOperationType.Delete: queueEntry = new PubSubNotifyQueueEntry(itm.GetType(), PubSubEventType.Delete, itm); break; } this.m_queue.Enqueue(PubSubBroker.QueueName, queueEntry); } }
/// <summary> /// Obsoletes the specified storage data. /// </summary> /// <param name="storageData">The storage data.</param> /// <param name="overrideAuthContext">The principal to use instead of the default.</param> /// <param name="mode">The mode.</param> /// <returns>TModel.</returns> public TModel Obsolete(TModel storageData, TransactionMode mode, IPrincipal overrideAuthContext = null) { if (storageData == null) { throw new ArgumentNullException(nameof(storageData), "Value cannot be null"); } if (!storageData.Key.HasValue || storageData.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } var prePersistenceEventArgs = new DataPersistingEventArgs <TModel>(storageData, overrideAuthContext); this.Obsoleting?.Invoke(this, prePersistenceEventArgs); if (prePersistenceEventArgs.Cancel) { traceSource.TraceEvent(EventLevel.Warning, $"Pre-event handler indicates abort for {storageData}"); return(storageData); } using (var connection = Configuration.Provider.GetWriteConnection()) { connection.Open(); using (var transaction = connection.BeginTransaction()) { try { this.traceSource.TraceEvent(EventLevel.Verbose, $"OBSOLETE {storageData}"); storageData = this.Obsolete(connection, storageData); if (mode == TransactionMode.Commit) { transaction.Commit(); } else { transaction.Rollback(); } var args = new DataPersistedEventArgs <TModel>(storageData, overrideAuthContext); this.Obsoleted?.Invoke(this, args); return(storageData); } catch (Exception e) { traceSource.TraceEvent(EventLevel.Error, $"Error obsoleting: {storageData}"); transaction.Rollback(); throw new DataPersistenceException(e.Message, e); } } } }
/// <summary> /// Recheck the bundle trigger to ensure the relationships make sense /// </summary> private void RecheckBundleTrigger(object sender, DataPersistedEventArgs <Bundle> e) { foreach (var itm in e.Data.Item.OfType <ITargetedVersionedExtension>()) { this.RecheckRelationship(itm, e.Mode, e.Principal); } // Remove dependent objects from cache foreach (var itm in e.Data.Item.OfType <IHasRelationships>()) { foreach (var rel in itm.Relationships.OfType <ITargetedVersionedExtension>()) { this.RecheckRelationship(rel, e.Mode, e.Principal); } } }
/// <summary> /// Represents when the ADT registration occurs /// </summary> protected void AdtPatientRegistrationInterceptor_Behavior(object sender, DataPersistedEventArgs <Patient> e) { ApplicationServiceContext.Current.GetService <IThreadPoolService>().QueueNonPooledWorkItem( (p) => { AuthenticationContext.Current = new AuthenticationContext(AuthenticationContext.SystemPrincipal); Patient pat = p as Patient; // We want to construct an ADT message if (and only if) the guards are met and if the last ADT was not this version var tag = pat.LoadCollection <EntityTag>("Tags").FirstOrDefault(o => o.TagKey == TagName); if (tag?.Value == e.Data.VersionKey.ToString()) { return; // No need } else if (base.ExecuteGuard(pat)) { // Perform notification IMessage notificationMessage; IGroup patientGroup; if (tag?.Value == null) { // Set the tag value and send an ADMIT patientGroup = notificationMessage = new ADT_A01(); ApplicationServiceContext.Current.GetService <ITagPersistenceService>().Save(pat.Key.Value, new EntityTag(TagName, pat.VersionKey.ToString())); (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value = "A04"; (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A01"; } else if (pat.LoadCollection <EntityRelationship>("Relationships").Any(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Replaces && o.EffectiveVersionSequenceId == pat.VersionSequence)) { // Set the tag value and send an ADMIT notificationMessage = new ADT_A39(); patientGroup = (notificationMessage as ADT_A39).GetPATIENT(); ApplicationServiceContext.Current.GetService <ITagPersistenceService>().Save(pat.Key.Value, new EntityTag(TagName, pat.VersionKey.ToString())); (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value = "A40"; (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A40"; foreach (var mrg in pat.LoadCollection <EntityRelationship>("Relationships").Where(o => o.RelationshipTypeKey == EntityRelationshipTypeKeys.Replaces && o.EffectiveVersionSequenceId == pat.VersionSequence)) { var seg = patientGroup.GetStructure("MRG", patientGroup.GetAll("MRG").Length) as MRG; if (this.Configuration.ExportDomains.Any(o => o.DomainName == this.m_configuration.LocalAuthority.DomainName)) { var key = seg.PriorAlternatePatientIDRepetitionsUsed; seg.GetPriorAlternatePatientID(key).IDNumber.Value = mrg.TargetEntityKey.Value.ToString(); seg.GetPriorAlternatePatientID(key).IdentifierTypeCode.Value = "PI"; seg.GetPriorAlternatePatientID(key).AssigningAuthority.NamespaceID.Value = this.m_configuration.LocalAuthority.DomainName; seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalID.Value = this.m_configuration.LocalAuthority.Oid; seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalIDType.Value = "ISO"; } // Alternate identifiers foreach (var extrn in pat.LoadCollection <EntityIdentifier>("Identifiers")) { var key = seg.PriorAlternatePatientIDRepetitionsUsed; if (this.Configuration.ExportDomains.Any(o => o.DomainName == extrn.LoadProperty <AssigningAuthority>("Authority").DomainName)) { seg.GetPriorAlternatePatientID(key).IDNumber.Value = extrn.Value; seg.GetPriorAlternatePatientID(key).IdentifierTypeCode.Value = "PT"; seg.GetPriorAlternatePatientID(key).AssigningAuthority.NamespaceID.Value = extrn.LoadProperty <AssigningAuthority>("Authority")?.DomainName; seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalID.Value = extrn.LoadProperty <AssigningAuthority>("Authority")?.Oid; seg.GetPriorAlternatePatientID(key).AssigningAuthority.UniversalIDType.Value = "ISO"; } } } } else { // Set the tag value and send an ADMIT patientGroup = notificationMessage = new ADT_A01(); ApplicationServiceContext.Current.GetService <ITagPersistenceService>().Save(pat.Key.Value, new EntityTag(TagName, pat.VersionKey.ToString())); (notificationMessage.GetStructure("MSH") as MSH).MessageType.TriggerEvent.Value = "A08"; (notificationMessage.GetStructure("MSH") as MSH).MessageType.MessageStructure.Value = "ADT_A08"; } if (!String.IsNullOrEmpty(this.Configuration.Version)) { (notificationMessage.GetStructure("MSH") as MSH).VersionID.VersionID.Value = this.Configuration.Version; } // Add SFT if (new Version(this.Configuration.Version ?? "2.5") >= new Version(2, 4)) { (notificationMessage.GetStructure("SFT", 0) as SFT).SetDefault(); } // Create the PID segment SegmentHandlers.GetSegmentHandler("PID").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray()); SegmentHandlers.GetSegmentHandler("PD1").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray()); SegmentHandlers.GetSegmentHandler("NK1").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray()); //SegmentHandlers.GetSegmentHandler("EVN").Create(e.Data, patientGroup, this.Configuration.ExportDomains.ToArray()); foreach (var itm in this.Configuration.Endpoints) { try { // TODO: Create an HL7 Queue (notificationMessage.GetStructure("MSH") as MSH).SetDefault(itm.ReceivingDevice, itm.ReceivingFacility, itm.SecurityToken); var response = itm.GetSender().SendAndReceive(notificationMessage); if (!(response.GetStructure("MSA") as MSA).AcknowledgmentCode.Value.EndsWith("A")) { throw new HL7Exception("Remote server rejected message"); } } catch (Exception ex) { this.m_tracer.TraceEvent(EventLevel.Error, "Error dispatching message {0} to {1}: {2} \r\n {3}", pat, itm.Address, ex, new PipeParser().Encode(notificationMessage)); } } } }, e.Data ); }
/// <summary> /// Notify obsoleted /// </summary> protected override void OnObsoleted(object sender, DataPersistedEventArgs <Bundle> evt) { this.OnInserted(sender, evt); }
/// <summary> /// Fire inserting event /// </summary> protected void FireInserted(DataPersistedEventArgs <TData> evt) { this.Inserted?.Invoke(this, evt); }
/// <summary> /// Obsoletes the specified object /// </summary> public TData Obsolete(TData data, TransactionMode mode, IPrincipal overrideAuthContext) { if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (data.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, overrideAuthContext); this.Obsoleting?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort for {0}", data); return(data); } // Obsolete object using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetWriteConnection()) { try { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { //connection.Connection.Open(); this.m_tracer.TraceEvent(EventLevel.Verbose, "OBSOLETE {0}", data); connection.EstablishProvenance(overrideAuthContext, (data as BaseEntityData)?.ObsoletedByKey); data = this.Obsolete(connection, data); if (mode == TransactionMode.Commit) { tx.Commit(); var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>(); cacheService?.Remove(data); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TData>(data, mode, overrideAuthContext); this.Obsoleted?.Invoke(this, args); return(data); } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e); tx?.Rollback(); throw new DataPersistenceException(e.Message, e); } finally { } } finally { } } }
/// <summary> /// Update the specified object /// </summary> /// <param name="storageData"></param> /// <param name="principal"></param> /// <param name="mode"></param> /// <returns></returns> public TData Update(TData data, TransactionMode mode, IPrincipal overrideAuthContext) { if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (data.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, overrideAuthContext); this.Updating?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort update for {0}", data); return(data); } // Persist object using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetWriteConnection()) { try { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { //connection.Connection.Open(); this.m_tracer.TraceEvent(EventLevel.Verbose, "UPDATE {0}", data); connection.EstablishProvenance(overrideAuthContext, (data as NonVersionedEntityData)?.UpdatedByKey ?? (data as BaseEntityData)?.CreatedByKey); data = Update(connection, data); data.LoadState = LoadState.FullLoad; // We just persisted this so it is fully loaded if (mode == TransactionMode.Commit) { tx.Commit(); var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>(); cacheService?.Remove(data); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TData>(data, mode, overrideAuthContext); this.Updated?.Invoke(this, args); return(data); } catch (DbException e) { #if DEBUG this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e.Message); #endif tx?.Rollback(); throw new DataPersistenceException($"Error updating {data}", this.TranslateDbException(e)); } catch (Exception e) { #if DEBUG this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e.Message); #endif tx?.Rollback(); // if the exception is key not found, we want the caller to know // so that a potential insert can take place if (e is KeyNotFoundException) { throw new KeyNotFoundException($"Record {data} was not found for update", e); } // if the exception is anything else, we want to throw a data persistence exception throw new DataPersistenceException($"Error updating {data}", e); } finally { } } finally { } } }
/// <summary> /// Inserts the specified data /// </summary> public TData Insert(TData data, TransactionMode mode, IPrincipal overrideAuthContext) { if (data == null) { throw new ArgumentNullException(nameof(data)); } DataPersistingEventArgs <TData> preArgs = new DataPersistingEventArgs <TData>(data, mode, overrideAuthContext); this.Inserting?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort insert for {0}", data); return(data); } // Persist object using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetWriteConnection()) { try { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { // Disable inserting duplicate classified objects connection.EstablishProvenance(overrideAuthContext, (data as BaseEntityData)?.CreatedByKey); var existing = data.TryGetExisting(connection, true); if (existing != null) { if (this.m_settingsProvider.GetConfiguration().AutoUpdateExisting) { this.m_tracer.TraceEvent(EventLevel.Warning, "INSERT WOULD RESULT IN DUPLICATE CLASSIFIER: UPDATING INSTEAD {0}", data); data.Key = existing.Key; data = this.Update(connection, data); } else { throw new DuplicateNameException(data.Key?.ToString()); } } else { this.m_tracer.TraceEvent(EventLevel.Verbose, "INSERT {0}", data); data = this.Insert(connection, data); } data.LoadState = LoadState.FullLoad; // We just persisted so it is fully loaded if (mode == TransactionMode.Commit) { tx.Commit(); var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>(); cacheService?.Add(data); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TData>(data, mode, overrideAuthContext); this.Inserted?.Invoke(this, args); return(data); } catch (DbException e) { #if DEBUG this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e.Message); #endif tx?.Rollback(); throw new DataPersistenceException($"Error inserting {data}", this.TranslateDbException(e)); } catch (DataPersistenceException) { throw; } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0} -- {1}", e, this.ObjectToString(data)); tx?.Rollback(); throw new DataPersistenceException(e.Message, e); } finally { } } finally { } } }
/// <summary> /// Insert the specified audit into the database /// </summary> public AuditData Insert(AuditData storageData, TransactionMode mode, IPrincipal overrideAuthContext = null) { // Pre-event trigger var preEvtData = new DataPersistingEventArgs <AuditData>(storageData, overrideAuthContext); this.Inserting?.Invoke(this, preEvtData); if (preEvtData.Cancel) { this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort insert {0}", storageData); return(storageData); } // Insert using (var context = this.m_configuration.Provider.GetWriteConnection()) { IDbTransaction tx = null; try { context.Open(); tx = context.BeginTransaction(); // Insert core var dbAudit = this.m_mapper.MapModelInstance <AuditData, DbAuditData>(storageData); var eventId = storageData.EventTypeCode; if (eventId != null) { var existing = context.FirstOrDefault <DbAuditCode>(o => o.Code == eventId.Code && o.CodeSystem == eventId.CodeSystem); if (existing == null) { Guid codeId = Guid.NewGuid(); dbAudit.EventTypeCode = codeId; context.Insert(new DbAuditCode() { Code = eventId.Code, CodeSystem = eventId.CodeSystem, Key = codeId }); } else { dbAudit.EventTypeCode = existing.Key; } } dbAudit.CreationTime = DateTime.Now; storageData.Key = Guid.NewGuid(); dbAudit.Key = storageData.Key.Value; context.Insert(dbAudit); // Insert secondary properties if (storageData.Actors != null) { foreach (var act in storageData.Actors) { var dbAct = context.FirstOrDefault <DbAuditActor>(o => o.UserName == act.UserName); if (dbAct == null) { dbAct = this.m_mapper.MapModelInstance <AuditActorData, DbAuditActor>(act); dbAct.Key = Guid.NewGuid(); var roleCode = act.ActorRoleCode?.FirstOrDefault(); if (roleCode != null) { var existing = context.FirstOrDefault <DbAuditCode>(o => o.Code == roleCode.Code && o.CodeSystem == roleCode.CodeSystem); if (existing == null) { dbAct.ActorRoleCode = Guid.NewGuid(); context.Insert(new DbAuditCode() { Code = roleCode.Code, CodeSystem = roleCode.CodeSystem, Key = dbAct.ActorRoleCode }); } else { dbAct.ActorRoleCode = existing.Key; } } context.Insert(dbAct); } context.Insert(new DbAuditActorAssociation() { TargetKey = dbAct.Key, SourceKey = dbAudit.Key, UserIsRequestor = act.UserIsRequestor, AccessPoint = act.NetworkAccessPointId, Key = Guid.NewGuid() }); } } // Audit objects if (storageData.AuditableObjects != null) { foreach (var ao in storageData.AuditableObjects) { var dbAo = this.m_mapper.MapModelInstance <AuditableObject, DbAuditObject>(ao); dbAo.IDTypeCode = (int)(ao.IDTypeCode ?? 0); dbAo.LifecycleType = (int)(ao.LifecycleType ?? 0); dbAo.Role = (int)(ao.Role ?? 0); dbAo.Type = (int)(ao.Type); dbAo.AuditId = dbAudit.Key; dbAo.Key = Guid.NewGuid(); context.Insert(dbAo); } } // metadata if (storageData.Metadata != null) { foreach (var meta in storageData.Metadata.Where(o => !String.IsNullOrEmpty(o.Value))) { context.Insert(new DbAuditMetadata() { AuditId = dbAudit.Key, MetadataKey = (int)meta.Key, Value = meta.Value }); } } if (mode == TransactionMode.Commit) { tx.Commit(); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <AuditData>(storageData, overrideAuthContext); this.Inserted?.Invoke(this, args); return(storageData); } catch (Exception ex) { tx?.Rollback(); throw new Exception($"Error inserting audit {storageData.Key}", ex); } } }
/// <summary> /// Insert the specified audit into the database /// </summary> public AuditData Insert(AuditData storageData, TransactionMode mode, IPrincipal overrideAuthContext = null) { // Pre-event trigger var preEvtData = new DataPersistingEventArgs <AuditData>(storageData, mode, overrideAuthContext); this.Inserting?.Invoke(this, preEvtData); if (preEvtData.Cancel) { this.m_traceSource.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort insert {0}", storageData); return(storageData); } // Insert using (var context = this.m_configuration.Provider.GetWriteConnection()) { IDbTransaction tx = null; try { context.Open(); tx = context.BeginTransaction(); // Insert core var dbAudit = this.m_mapper.MapModelInstance <AuditData, DbAuditData>(storageData); var eventId = storageData.EventTypeCode; if (eventId != null) { dbAudit.EventTypeCode = this.GetOrCreateAuditCode(context, eventId).Key; } dbAudit.CreationTime = DateTimeOffset.Now; storageData.Key = Guid.NewGuid(); dbAudit.Key = storageData.Key.Value; context.Insert(dbAudit); // Insert secondary properties if (storageData.Actors != null) { foreach (var act in storageData.Actors) { var roleCode = this.GetOrCreateAuditCode(context, act.ActorRoleCode.FirstOrDefault()); DbAuditActor dbAct = null; if (roleCode != null) { dbAct = context.FirstOrDefault <DbAuditActor>(o => o.UserName == act.UserName && o.ActorRoleCode == roleCode.Key); } else { dbAct = context.FirstOrDefault <DbAuditActor>(o => o.UserName == act.UserName && o.ActorRoleCode == Guid.Empty); } if (dbAct == null) { dbAct = this.m_mapper.MapModelInstance <AuditActorData, DbAuditActor>(act); dbAct.ActorRoleCode = roleCode?.Key ?? Guid.Empty; dbAct = context.Insert(dbAct); } context.Insert(new DbAuditActorAssociation() { TargetKey = dbAct.Key, SourceKey = dbAudit.Key, UserIsRequestor = act.UserIsRequestor, AccessPoint = act.NetworkAccessPointId }); } } // Audit objects if (storageData.AuditableObjects != null) { foreach (var ao in storageData.AuditableObjects) { var dbAo = this.m_mapper.MapModelInstance <AuditableObject, DbAuditObject>(ao); dbAo.IDTypeCode = (int)(ao.IDTypeCode ?? 0); dbAo.LifecycleType = (int)(ao.LifecycleType ?? 0); dbAo.Role = (int)(ao.Role ?? 0); dbAo.Type = (int)(ao.Type); dbAo.AuditId = dbAudit.Key; if (ao.CustomIdTypeCode != null) { var code = this.GetOrCreateAuditCode(context, ao.CustomIdTypeCode); dbAo.CustomIdType = code.Key; } dbAo = context.Insert(dbAo); if (ao.ObjectData?.Count > 0) { foreach (var od in ao.ObjectData) { context.Insert(new DbAuditObjectData() { Name = od.Key, Value = od.Value, ObjectId = dbAo.Key }); } } } } // metadata if (storageData.Metadata != null) { foreach (var meta in storageData.Metadata.Where(o => !String.IsNullOrEmpty(o.Value) && o.Key != AuditMetadataKey.CorrelationToken)) { var kv = context.FirstOrDefault <DbAuditMetadataValue>(o => o.Value == meta.Value); if (kv == null) { kv = context.Insert(new DbAuditMetadataValue() { // TODO: Make this a common extension function (to trim) Value = meta.Value.Substring(0, meta.Value.Length > 256 ? 256 : meta.Value.Length) }); } context.Insert(new DbAuditMetadata() { AuditId = dbAudit.Key, MetadataKey = (int)meta.Key, ValueId = kv.Key }); } } if (mode == TransactionMode.Commit) { tx.Commit(); } else { tx.Rollback(); } var args = new DataPersistedEventArgs <AuditData>(storageData, mode, overrideAuthContext); this.Inserted?.Invoke(this, args); return(storageData); } catch (Exception ex) { tx?.Rollback(); throw new Exception($"Error inserting audit {storageData.Key}", ex); } } }
/// <summary> /// Update the specified container /// </summary> /// <param name="data">The data to be updated</param> /// <param name="principal">The principal for authorization</param> /// <param name="mode">The mode of operation</param> /// <returns>The updated model</returns> public TModel Update(TModel data, TransactionMode mode, IPrincipal principal) { if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (data.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal); this.Updating?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event handler indicates abort update for {0}", data); return(data); } // Persist object using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection()) { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { //connection.Connection.Open(); connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.UpdatedByKey ?? (data as BaseEntityData)?.CreatedByKey); this.m_tracer.TraceVerbose("UPDATE {0}", data); data = this.UpdateInternal(connection, data, principal); connection.AddCacheCommit(data); data.LoadState = LoadState.FullLoad; // We just persisted this so it is fully loaded if (mode == TransactionMode.Commit) { tx.Commit(); foreach (var itm in connection.CacheOnCommit) { ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(itm); } } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TModel>(data, mode, principal); this.Updated?.Invoke(this, args); return(data); } catch (DbException e) { #if DEBUG this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceError("Error : {0}", e.Message); #endif tx?.Rollback(); this.TranslateDbException(e); throw; } catch (Exception e) { #if DEBUG this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceError("Error : {0}", e.Message); #endif tx?.Rollback(); // if the exception is key not found, we want the caller to know // so that a potential insert can take place if (e is KeyNotFoundException) { throw new KeyNotFoundException(e.Message, e); } // if the exception is anything else, we want to throw a data persistence exception throw new DataPersistenceException(e.Message, e); } finally { } } }
/// <summary> /// Obsolete the specified key data /// </summary> /// <param name="storageData">The storage data to be obsoleted</param> /// <param name="principal">The principal to use to obsolete</param> /// <param name="mode">The mode of obsoletion</param> /// <returns>The obsoleted record</returns> public TModel Obsolete(TModel data, TransactionMode mode, IPrincipal principal) { if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (data.Key == Guid.Empty) { throw new InvalidOperationException("Data missing key"); } DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal); this.Obsoleting?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event handler indicates abort for {0}", data); return(data); } // Obsolete object using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection()) { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { //connection.Connection.Open(); this.m_tracer.TraceVerbose("OBSOLETE {0}", data); connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.ObsoletedByKey ?? (data as BaseEntityData)?.ObsoletedByKey); data = this.ObsoleteInternal(connection, data, principal); connection.AddCacheCommit(data); if (mode == TransactionMode.Commit) { tx.Commit(); foreach (var itm in connection.CacheOnCommit) { ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Remove(itm.Key.Value); } } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TModel>(data, mode, principal); this.Obsoleted?.Invoke(this, args); return(data); } catch (Exception e) { this.m_tracer.TraceError("Error : {0}", e); tx?.Rollback(); throw new DataPersistenceException(e.Message, e); } finally { } } }
/// <summary> /// Insert the specified storage data /// </summary> /// <param name="data">The storage data to be inserted</param> /// <param name="principal">The authentication context</param> /// <param name="mode">The transaction control mode</param> /// <returns>The inserted data</returns> public TModel Insert(TModel data, TransactionMode mode, IPrincipal principal) { if (data == null) { throw new ArgumentNullException(nameof(data)); } DataPersistingEventArgs <TModel> preArgs = new DataPersistingEventArgs <TModel>(data, mode, principal); this.Inserting?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event handler indicates abort insert for {0}", data); return(data); } // Persist object using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetWriteConnection()) { connection.Open(); using (IDbTransaction tx = connection.BeginTransaction()) try { connection.EstablishProvenance(principal, (data as NonVersionedEntityData)?.CreatedByKey ?? (data as BaseEntityData)?.CreatedByKey); // Disable inserting duplicate classified objects var existing = data.TryGetExisting(connection, principal, true); if (existing != null) { throw new DuplicateNameException(data.Key?.ToString()); } else { this.m_tracer.TraceVerbose("INSERT {0}", data); data = this.InsertInternal(connection, data, principal); connection.AddCacheCommit(data); } data.LoadState = LoadState.FullLoad; // We just persisted so it is fully loaded if (mode == TransactionMode.Commit) { tx.Commit(); foreach (var itm in connection.CacheOnCommit) { ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(itm); } } else { tx.Rollback(); } var args = new DataPersistedEventArgs <TModel>(data, mode, principal); this.Inserted?.Invoke(this, args); return(data); } catch (DbException e) { #if DEBUG this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data)); #else this.m_tracer.TraceError("Error : {0}", e.Message); #endif tx?.Rollback(); this.TranslateDbException(e); throw; } catch (Exception e) { this.m_tracer.TraceError("Error : {0} -- {1}", e, this.ObjectToString(data)); tx?.Rollback(); throw new DataPersistenceException(e.Message, e); } } }
/// <summary> /// Re-check relationships to ensure that they are properly in the database /// </summary> private void RecheckRelationshipTrigger(object sender, DataPersistedEventArgs <EntityRelationship> e) { this.RecheckRelationship(e.Data, e.Mode, e.Principal); this.m_dataCachingService.Remove(e.Data); }