/// <summary> /// Find a client /// </summary> public Client FindClient(DomainIdentifier identifier) { PersonPersister persister = new PersonPersister(); // HACK: I norder to work around Client Registry Hack ApplicationContext.CurrentContext = Context; // First we want to find the appropriate helper IDbConnection conn = DatabasePersistenceService.ReadOnlyConnectionManager.GetConnection(); try { var tPerson = persister.GetPerson(conn, null, identifier, true); Client retVal = new Client() { AlternateIdentifiers = tPerson.AlternateIdentifiers, BirthTime = tPerson.BirthTime, GenderCode = tPerson.GenderCode, Id = tPerson.Id, IsMasked = tPerson.IsMasked, LegalName = tPerson.Names == null || tPerson.Names.Count == 0 ? null : tPerson.Names.Find(n => n.Use == NameSet.NameSetUse.Legal) ?? tPerson.Names[0], PerminantAddress = tPerson.Addresses == null || tPerson.Addresses.Count == 0 ? null : tPerson.Addresses.Find(n => n.Use == AddressSet.AddressSetUse.HomeAddress) ?? tPerson.Addresses[0], TelecomAddresses = tPerson.TelecomAddresses }; retVal.Add(tPerson, "PSN", SVC.Core.ComponentModel.HealthServiceRecordSiteRoleType.TargetOf, null); return(retVal); } finally { DatabasePersistenceService.ConnectionManager.ReleaseConnection(conn); } }
/// <summary> /// Persist the person relationship /// </summary> public SVC.Core.DataTypes.VersionedDomainIdentifier Persist(System.Data.IDbConnection conn, System.Data.IDbTransaction tx, System.ComponentModel.IComponent data, bool isUpdate) { // Is this a replacement var pp = new PersonPersister(); PersonRegistrationRef refr = data as PersonRegistrationRef; Person psn = pp.GetPerson(conn, tx, refr.AlternateIdentifiers[0], true); Person cntrPsn = data.Site.Container as Person; if (psn == null || cntrPsn == null) { throw new ConstraintException(ApplicationContext.LocaleService.GetString("DBCF00B")); } else if (psn.Id == cntrPsn.Id) { throw new ConstraintException(ApplicationContext.LocaleService.GetString("DBCF00D")); } // Load the container person from DB so we get all data Person dbCntrPsn = pp.GetPerson(conn, tx, new SVC.Core.DataTypes.DomainIdentifier() { Domain = ApplicationContext.ConfigurationService.OidRegistrar.GetOid(ClientRegistryOids.CLIENT_CRID).Oid, Identifier = cntrPsn.Id.ToString() }, true); pp.MergePersons(dbCntrPsn, cntrPsn); // Load the components for the person #if DEBUG Trace.TraceInformation("Registration reference {0} > {1}", psn.Id, dbCntrPsn.Id); #endif DbUtil.DePersistComponents(conn, psn, this, true); if (psn == null || dbCntrPsn == null) { throw new ConstraintException(ApplicationContext.LocaleService.GetString("DBCF00B")); } dbCntrPsn.Site = (data.Site.Container as IComponent).Site; var role = (refr.Site as HealthServiceRecordSite).SiteRoleType; var symbolic = (refr.Site as HealthServiceRecordSite).IsSymbolic; // If true, the replacement does not cascade and is a symbolic replacement of only the identifiers listed // Replacement? if (role == HealthServiceRecordSiteRoleType.ReplacementOf) { // First, we obsolete all records with the existing person foreach (var id in psn.AlternateIdentifiers.FindAll(o => refr.AlternateIdentifiers.Exists(a => a.Domain == o.Domain))) { id.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Remove; } //psn.AlternateIdentifiers.RemoveAll(o => o.UpdateMode != SVC.Core.DataTypes.UpdateModeType.Remove); // Not symbolic, means that we do a hard replace // Symbolic replace = Just replace the reference to that identifier // Hard replace = Merge the new and old record and then replace them if (!symbolic) { #if DEBUG Trace.TraceInformation("Performing an administrative migration of identifiers and information from {0} > {1}", psn.Id, dbCntrPsn.Id); #endif // Now to copy the components of the current version down //foreach (IComponent cmp in refr.Site.Container.Components) // if (cmp != refr) // dbCntrPsn.Add((cmp as HealthServiceRecordComponent).Clone() as IComponent); // Merge the two records in memory taking the newer data // This is a merge from old to new in order to capture any data elements // that have been updated in the old that might be newer (or more accurate) than the // the new if (psn.AlternateIdentifiers == null) { dbCntrPsn.AlternateIdentifiers = new List <SVC.Core.DataTypes.DomainIdentifier>(); } else if (psn.OtherIdentifiers == null) { dbCntrPsn.OtherIdentifiers = new List <KeyValuePair <SVC.Core.DataTypes.CodeValue, SVC.Core.DataTypes.DomainIdentifier> >(); } foreach (var id in psn.AlternateIdentifiers) { // Remove the identifier from the original id.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Remove; // If this is a duplicate id then don't add if (dbCntrPsn.AlternateIdentifiers.Exists(i => i.Domain == id.Domain && i.Identifier == id.Identifier)) { continue; } bool isPrivate = false; var oidData = ApplicationContext.ConfigurationService.OidRegistrar.FindData(id.Domain); if (oidData != null) { isPrivate = !(oidData.Attributes.Exists(o => o.Key == "IsMergeSurvivor") && Convert.ToBoolean(oidData.Attributes.Find(o => o.Key == "IsMergeSurvivor").Value)); } // Add to alternate identifiers dbCntrPsn.AlternateIdentifiers.Add(new SVC.Core.DataTypes.DomainIdentifier() { AssigningAuthority = id.AssigningAuthority, UpdateMode = SVC.Core.DataTypes.UpdateModeType.AddOrUpdate, IsLicenseAuthority = false, IsPrivate = isPrivate, // TODO: Make this a configuration flag (cntrPsn.AlternateIdentifiers.Exists(i=>i.Domain == id.Domain)), Identifier = id.Identifier, Domain = id.Domain }); } foreach (var id in psn.OtherIdentifiers) { // Remove the identifier from the original id.Value.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Remove; // If this is a duplicate id then don't add if (dbCntrPsn.OtherIdentifiers.Exists(i => i.Value.Domain == id.Value.Domain && i.Value.Identifier == id.Value.Identifier)) { continue; } // Add to other identifiers var oth = new KeyValuePair <SVC.Core.DataTypes.CodeValue, SVC.Core.DataTypes.DomainIdentifier>( id.Key, new SVC.Core.DataTypes.DomainIdentifier() { AssigningAuthority = id.Value.AssigningAuthority, UpdateMode = SVC.Core.DataTypes.UpdateModeType.Add, IsLicenseAuthority = false, IsPrivate = (dbCntrPsn.OtherIdentifiers.Exists(i => i.Value.Domain == id.Value.Domain)), Identifier = id.Value.Identifier, Domain = id.Value.Domain }); // Copy extensions var extns = psn.FindAllExtensions(o => o.PropertyPath == String.Format("OtherIdentifiers[{0}{1}]", oth.Value.Domain, oth.Value.Identifier)); if (extns != null) { foreach (var ex in extns) { if (dbCntrPsn.FindExtension(o => o.PropertyPath == ex.PropertyPath && o.Name == ex.Name) == null) { dbCntrPsn.Add(ex); } } } dbCntrPsn.OtherIdentifiers.Add(oth); } // Make sure we don't update what we don't need to dbCntrPsn.Addresses = psn.Addresses = null; dbCntrPsn.Citizenship = psn.Citizenship = null; dbCntrPsn.Employment = psn.Employment = null; dbCntrPsn.Language = psn.Language = null; dbCntrPsn.Names = psn.Names = null; dbCntrPsn.Race = psn.Race = null; dbCntrPsn.TelecomAddresses = psn.TelecomAddresses = null; dbCntrPsn.BirthTime = psn.BirthTime = null; dbCntrPsn.DeceasedTime = psn.DeceasedTime = null; // Remove the old person from the db psn.Status = SVC.Core.ComponentModel.Components.StatusType.Obsolete; // obsolete the old person } else // migrate identifiers { foreach (var id in refr.AlternateIdentifiers) { bool isPrivate = false; var oidData = ApplicationContext.ConfigurationService.OidRegistrar.FindData(id.Domain); if (oidData != null) { isPrivate = !(oidData.Attributes.Exists(o => o.Key == "IsMergeSurvivor") && Convert.ToBoolean(oidData.Attributes.Find(o => o.Key == "IsMergeSurvivor").Value)); } dbCntrPsn.AlternateIdentifiers.Add(new SVC.Core.DataTypes.DomainIdentifier() { AssigningAuthority = id.AssigningAuthority, UpdateMode = SVC.Core.DataTypes.UpdateModeType.AddOrUpdate, IsLicenseAuthority = false, IsPrivate = isPrivate, // TODO: Make this a configuration flag (cntrPsn.AlternateIdentifiers.Exists(i=>i.Domain == id.Domain)), Identifier = id.Identifier, Domain = id.Domain }); } // set to ignore if (psn.Names != null) { foreach (var rc in psn.Names) { rc.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Ignore; } } // set to ignore if (psn.Addresses != null) { foreach (var rc in psn.Addresses) { rc.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Ignore; } } // set to ignore if (psn.Race != null) { foreach (var rc in psn.Race) { rc.UpdateMode = SVC.Core.DataTypes.UpdateModeType.Ignore; } } } // Now update the person //psn.Site = refr.Site; //pp.Persist(conn, tx, psn, true); // update the person record #if DEBUG Trace.TraceInformation("Step 1 : Prepare update to person #{0}", psn.Id, cntrPsn.Id, !symbolic); #endif var regEvent = this.GetRegistrationEvent(conn, tx, psn); // get the registration event var changeSummary = DbUtil.GetRegistrationEvent(refr).FindComponent(HealthServiceRecordSiteRoleType.ReasonFor | HealthServiceRecordSiteRoleType.OlderVersionOf) as ChangeSummary; if (changeSummary != null) { regEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.ReasonFor | HealthServiceRecordSiteRoleType.OlderVersionOf); regEvent.Add(new ChangeSummary() { ChangeType = changeSummary.ChangeType, EffectiveTime = changeSummary.EffectiveTime, LanguageCode = changeSummary.LanguageCode, Status = changeSummary.Status, Timestamp = changeSummary.Timestamp }, "CHG", HealthServiceRecordSiteRoleType.ReasonFor | HealthServiceRecordSiteRoleType.OlderVersionOf, null); } if (!symbolic) { regEvent.Status = StatusType.Obsolete; // obsolete } regEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.SubjectOf); regEvent.Add(psn, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); #if DEBUG Trace.TraceInformation("Step 2 : Perform update to person #{0}", psn.Id); #endif new RegistrationEventPersister().Persist(conn, tx, regEvent, true); refr.AlternateIdentifiers.Clear(); refr.AlternateIdentifiers.Add(new SVC.Core.DataTypes.DomainIdentifier() { Domain = ApplicationContext.ConfigurationService.OidRegistrar.GetOid("CR_CID").Oid, Identifier = psn.Id.ToString() }); //pp.CreatePersonVersion(conn, tx, psn); //DbUtil.PersistComponents(conn, tx, false, this, psn); // Now, we have to prepare an event so that this all makes sense // if we de-persist the most recent version (to reflect changes made) // Store the merged new record #if DEBUG Trace.TraceInformation("Step 3 : Perform update to person #{0}", dbCntrPsn.Id); #endif pp.CreatePersonVersion(conn, tx, dbCntrPsn); // Components DbUtil.PersistComponents(conn, tx, false, this, dbCntrPsn); // Now update the backreference to up the chain it gets updated cntrPsn.VersionId = dbCntrPsn.VersionId; } // Create the link #if DEBUG Trace.TraceInformation("Creating link between persons {0} > {1}", psn.Id, dbCntrPsn.Id); #endif using (var cmd = DbUtil.CreateCommandStoredProc(conn, tx)) { cmd.CommandText = "crt_psn_lnk"; cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "psn_id_in", DbType.Decimal, dbCntrPsn.Id)); cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "psn_vrsn_id_in", DbType.Decimal, dbCntrPsn.VersionId)); cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "lnk_psn_id_in", DbType.Decimal, psn.Id)); cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "lnk_cls_in", DbType.Decimal, (decimal)role)); cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "symbolic_in", DbType.Boolean, symbolic)); cmd.ExecuteNonQuery(); } // Send notification that duplicates were resolved //if (symbolic) //{ // // Send an duplicates resolved message // IClientNotificationService notificationService = ApplicationContext.CurrentContext.GetService(typeof(IClientNotificationService)) as IClientNotificationService; // if (notificationService != null) // notificationService.NotifyDuplicatesResolved(cntrPsn, refr.AlternateIdentifiers[0]); //} refr.Id = psn.Id; // Person identifier return(new SVC.Core.DataTypes.VersionedDomainIdentifier() { Identifier = psn.Id.ToString(), Version = psn.VersionId.ToString() }); }
/// <summary> /// Persist a component to the database /// </summary> public MARC.HI.EHRS.SVC.Core.DataTypes.VersionedDomainIdentifier Persist(System.Data.IDbConnection conn, System.Data.IDbTransaction tx, System.ComponentModel.IComponent data, bool isUpdate) { // Get config service ISystemConfigurationService configService = ApplicationContext.ConfigurationService; //ApplicationContext.Current.GetService(typeof(ISystemConfigurationService)) as ISystemConfigurationService; // Create the personal relationship in a strongly typed fashion PersonalRelationship pr = data as PersonalRelationship; Person clientContainer = pr.Site.Container as Person, relationshipPerson = null; // Get the person persister var persister = new PersonPersister(); // First, let's see if we can fetch the client if (pr.Id != default(decimal)) { var personalRelationship = this.DePersist(conn, pr.Id, pr.Site.Container, (pr.Site as HealthServiceRecordSite).SiteRoleType, true) as PersonalRelationship; relationshipPerson = personalRelationship.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person; } else if (pr.AlternateIdentifiers != null) { int i = 0; while (relationshipPerson == null && i < pr.AlternateIdentifiers.Count) { relationshipPerson = persister.GetPerson(conn, tx, pr.AlternateIdentifiers[i++], true); } } if (relationshipPerson == null) { List <DomainIdentifier> candidateId = new List <DomainIdentifier>(); // Is this an existing person (same name and relation) using (IDbCommand cmd = DbUtil.CreateCommandStoredProc(conn, tx)) { cmd.CommandText = "get_psn_rltnshps"; cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "src_psn_id_in", DbType.Decimal, clientContainer.Id)); cmd.Parameters.Add(DbUtil.CreateParameterIn(cmd, "src_psn_vrsn_id_in", DbType.Decimal, clientContainer.VersionId)); using (IDataReader rdr = cmd.ExecuteReader()) { while (rdr.Read()) { if (rdr["kind_cs"].ToString() == pr.RelationshipKind) { candidateId.Add(new DomainIdentifier() { Domain = configService.OidRegistrar.GetOid("CR_CID").Oid, Identifier = rdr["src_psn_id"].ToString() }); } } } } // Now load candidates and check foreach (var id in candidateId) { var candidate = persister.GetPerson(conn, tx, id, true); if (NON_DUPLICATE_REL.Contains(pr.RelationshipKind)) { relationshipPerson = candidate; break; } else if (candidate.Names.Exists(n => n.SimilarityTo(pr.LegalName) >= DatabasePersistenceService.ValidationSettings.PersonNameMatch)) { relationshipPerson = candidate; break; } } } // Did we get one? // If not, then we need to register a patient in the database if (relationshipPerson == null) { if (pr.LegalName == null) { throw new DataException(ApplicationContext.LocaleService.GetString("DBCF00B")); } relationshipPerson = new Person() { AlternateIdentifiers = pr.AlternateIdentifiers, Names = new List <NameSet>() { pr.LegalName }, Addresses = new List <AddressSet>() { pr.PerminantAddress }, GenderCode = pr.GenderCode, BirthTime = pr.BirthTime, TelecomAddresses = pr.TelecomAddresses, Status = StatusType.Active, RoleCode = PersonRole.PRS }; var registrationEvent = DbUtil.GetRegistrationEvent(pr).Clone() as RegistrationEvent; registrationEvent.Id = default(decimal); registrationEvent.EventClassifier = RegistrationEventType.ComponentEvent; registrationEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.SubjectOf); registrationEvent.Add(relationshipPerson, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); registrationEvent.Status = StatusType.Completed; // Persist or merge? new RegistrationEventPersister().Persist(conn, tx, registrationEvent, isUpdate); //var clientIdentifier = persister.Persist(conn, tx, relationshipPerson, isUpdate); // Should persist } else if (relationshipPerson.RoleCode != PersonRole.PAT) { var updatedPerson = new Person() { Id = relationshipPerson.Id, AlternateIdentifiers = pr.AlternateIdentifiers, Names = new List <NameSet>() { pr.LegalName }, Addresses = new List <AddressSet>() { }, GenderCode = pr.GenderCode, BirthTime = pr.BirthTime, TelecomAddresses = pr.TelecomAddresses, Status = StatusType.Active, RoleCode = relationshipPerson.RoleCode }; if (pr.PerminantAddress != null) { updatedPerson.Addresses.Add(pr.PerminantAddress); } persister.MergePersons(updatedPerson, relationshipPerson, true); relationshipPerson = updatedPerson; var registrationEvent = DbUtil.GetRegistrationEvent(pr).Clone() as RegistrationEvent; registrationEvent.Id = default(decimal); registrationEvent.EventClassifier = RegistrationEventType.ComponentEvent; registrationEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.SubjectOf); registrationEvent.Add(relationshipPerson, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); registrationEvent.Status = StatusType.Completed; new RegistrationEventPersister().Persist(conn, tx, registrationEvent, isUpdate); } // Validate if (!NON_DUPLICATE_REL.Contains(pr.RelationshipKind) && pr.AlternateIdentifiers.Count == 0 && !relationshipPerson.Names.Exists(o => QueryUtil.MatchName(pr.LegalName, o) >= DatabasePersistenceService.ValidationSettings.PersonNameMatch)) { throw new DataException(ApplicationContext.LocaleService.GetString("DBCF00A")); } // If the container for this personal relationship is a client, then we'll need to link that // personal relationship with the client to whom they have a relation with. if (clientContainer != null) // We need to do some linking { pr.Id = LinkClients(conn, tx, relationshipPerson.Id, clientContainer.Id, pr.RelationshipKind, pr.Status); } else if (clientContainer == null) // We need to do some digging to find out "who" this person is related to (the record target) { throw new ConstraintException(ApplicationContext.LocaleService.GetString("DBCF003")); } // todo: Container is a HSR return(new VersionedDomainIdentifier() { Domain = configService.OidRegistrar.GetOid(ClientRegistryOids.RELATIONSHIP_OID).Oid, Identifier = pr.Id.ToString() }); }
/// <summary> /// Update container /// </summary> public VersionedDomainIdentifier UpdateContainer(System.ComponentModel.IContainer storageData, DataPersistenceMode mode) { if (m_disposed) { throw new ObjectDisposedException("DatabasePersistenceService"); } if (storageData == null) { throw new ArgumentNullException("storageData"); } // Get the persister IComponentPersister persister = GetPersister(storageData.GetType()); ISystemConfigurationService configService = ApplicationContext.ConfigurationService; if (persister != null) { IDbTransaction tx = null; IDbConnection conn = null; try { conn = DatabasePersistenceService.ConnectionManager.GetConnection(); RegistrationEvent hsrEvent = storageData as RegistrationEvent; // Is the record something that we have access to? if (hsrEvent.AlternateIdentifier != null && !hsrEvent.AlternateIdentifier.Domain.Equals(configService.OidRegistrar.GetOid(ClientRegistryOids.REGISTRATION_EVENT).Oid)) { throw new ArgumentException(String.Format("The record OID '{0}' cannot be retrieved by this repository, expecting OID '{1}'", hsrEvent.AlternateIdentifier.Domain, configService.OidRegistrar.GetOid(ClientRegistryOids.REGISTRATION_EVENT).Oid)); } decimal tryDec = default(decimal); bool isDirectUpdate = false; // Is there no event identifier ? if (hsrEvent.AlternateIdentifier != null && !Decimal.TryParse(hsrEvent.AlternateIdentifier.Identifier, out tryDec)) { throw new ArgumentException(String.Format("The identifier '{0}' is not a valid identifier for this repository", hsrEvent.AlternateIdentifier.Identifier)); } else if (hsrEvent.AlternateIdentifier == null) // The alternate identifier is null ... so we need to look up the registration event to version ... interesting.... { this.EnrichRegistrationEvent(conn, tx, hsrEvent); } else { // Get the person name isDirectUpdate = true; // Explicit update } // Validate and duplicate the components that are to be loaded as part of the new version var oldHsrEvent = GetContainer(hsrEvent.AlternateIdentifier, true) as RegistrationEvent; // Get the old container if (oldHsrEvent == null) { throw new MissingPrimaryKeyException(String.Format("Record {1}^^^&{0}&ISO does not exist", hsrEvent.AlternateIdentifier.Domain, hsrEvent.AlternateIdentifier.Identifier)); } PersonPersister cp = new PersonPersister(); // Validate the old record target Person oldRecordTarget = oldHsrEvent.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person, newRecordTarget = hsrEvent.FindComponent(HealthServiceRecordSiteRoleType.SubjectOf) as Person; Person verifyRecordTarget = null; if (!isDirectUpdate) { Trace.TraceInformation("Not Direct update, enriching the Patient Data"); int idCheck = 0; while (verifyRecordTarget == null || idCheck > newRecordTarget.AlternateIdentifiers.Count) { verifyRecordTarget = cp.GetPerson(conn, null, newRecordTarget.AlternateIdentifiers[idCheck++], true); } if (verifyRecordTarget == null || oldRecordTarget.Id != verifyRecordTarget.Id) { throw new ConstraintException("The update request specifies a different subject than the request currently stored"); } } else { verifyRecordTarget = oldRecordTarget; } //newRecordTarget.VersionId = verifyRecordTarget.VersionId; newRecordTarget.Id = verifyRecordTarget.Id; // VAlidate classific if (oldHsrEvent.EventClassifier != hsrEvent.EventClassifier && (hsrEvent.EventClassifier & RegistrationEventType.Register) == RegistrationEventType.None) { throw new ConstraintException("Record type mis-match between update data and the data already in the persistence store"); } if (oldHsrEvent.LanguageCode != hsrEvent.LanguageCode) { throw new ConstraintException("Record language mis-match between update data and data already in persistence store. To change the language use a \"replaces\" relationship rather than an update"); } // Are we performing a component update? If so the only two components we want freshened are the CommentOn (for adding comments) // and the ReasonFor | OlderVersionOf comment for change summaries if ((hsrEvent.EventClassifier & RegistrationEventType.ComponentEvent) != 0) { for (int i = hsrEvent.XmlComponents.Count - 1; i >= 0; i--) { if (((hsrEvent.XmlComponents[i].Site as HealthServiceRecordSite).SiteRoleType & (HealthServiceRecordSiteRoleType.CommentOn | HealthServiceRecordSiteRoleType.ReasonFor | HealthServiceRecordSiteRoleType.OlderVersionOf | HealthServiceRecordSiteRoleType.TargetOf)) == 0) { hsrEvent.Remove(hsrEvent.XmlComponents[i]); } } } // Copy over any components that aren't already specified or updated in the new record // Merge the old and new. Sets the update mode appropriately cp.MergePersons(newRecordTarget, oldRecordTarget); // Next we copy this as a replacement of hsrEvent.RemoveAllFromRole(HealthServiceRecordSiteRoleType.SubjectOf); hsrEvent.Add(newRecordTarget, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null); // Begin and update tx = conn.BeginTransaction(); var retVal = persister.Persist(conn, tx, storageData as IComponent, true); if (m_configuration.OverridePersistenceMode.HasValue) { mode = m_configuration.OverridePersistenceMode.Value; } if (mode == DataPersistenceMode.Production) { tx.Commit(); tx = null; // Mark conflicts if any are outstanding pointing at the old versionj if (this.m_clientRegistryMerge != null) { var existingConflicts = this.m_clientRegistryMerge.GetConflicts(oldHsrEvent.AlternateIdentifier); if (existingConflicts.Count() > 0) { Trace.TraceInformation("Obsoleting existing conlflicts resolved"); this.m_clientRegistryMerge.ObsoleteConflicts(oldHsrEvent.AlternateIdentifier); } this.m_threadPool.QueueUserWorkItem(this.MarkConflictsAsync, retVal); } // Notify register if (this.m_notificationService != null) { if (hsrEvent.Mode == RegistrationEventType.Replace) { this.m_notificationService.NotifyDuplicatesResolved(hsrEvent); } else { this.m_notificationService.NotifyUpdate(hsrEvent); } } } else { tx.Rollback(); } return(retVal); } catch (Exception e) { if (tx != null) { tx.Rollback(); } throw; } finally { if (tx != null) { tx.Dispose(); } if (conn != null) { DatabasePersistenceService.ConnectionManager.ReleaseConnection(conn); conn = null; } } } else { Trace.TraceError("Can't find a persistence handler for type '{0}'", storageData.GetType().Name); throw new DataException(String.Format("Can't persist type '{0}'", storageData.GetType().Name)); } }