Пример #1
0
        /// <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));
            }
        }
Пример #2
0
        /// <summary>
        /// Store a container
        /// </summary>
        public VersionedDomainIdentifier StoreContainer(System.ComponentModel.IContainer storageData, DataPersistenceMode mode)
        {
            if (m_disposed)
            {
                throw new ObjectDisposedException("DatabasePersistenceService");
            }

            // Merge
            IEnumerable <VersionedDomainIdentifier> pid = null;
            var regEvent = storageData as RegistrationEvent;

            if (this.m_clientRegistryMerge != null && regEvent != null)
            {
                bool fuzzy = false;
                pid = this.m_clientRegistryMerge.FindIdConflicts(regEvent);


                // Do we have a match?
                if (pid.Count() == 0)                                                            // if we didn't find any id conflicts go to fuzzy mode
                {
                    if (this.m_clientRegistryConfiguration.Configuration.Registration.AutoMerge) // we have to do this now :(
                    {
                        fuzzy = true;
                        pid   = this.m_clientRegistryMerge.FindFuzzyConflicts(regEvent);
                        if (pid.Count() == 1)
                        {
                            regEvent.AlternateIdentifier = pid.First();
                            Trace.TraceInformation("Matched with {0} records (fuzzy={1}, autoOn={2}, updateEx={3})",
                                                   pid.Count(), fuzzy, this.m_clientRegistryConfiguration.Configuration.Registration.AutoMerge,
                                                   this.m_clientRegistryConfiguration.Configuration.Registration.UpdateIfExists);
                            return(this.UpdateContainer(regEvent, mode));
                        }
                    }
                }
                else if (this.m_clientRegistryConfiguration.Configuration.Registration.UpdateIfExists)
                {
                    // Update
                    if (pid.Count() == 1)
                    {
                        Trace.TraceInformation("Updating record {0} because it matched by identifier", regEvent.Id);
                        regEvent.AlternateIdentifier = pid.First();
                        return(this.UpdateContainer(regEvent, mode));
                    }
                }
            }
            else
            {
                pid = new List <VersionedDomainIdentifier>();
            }

            //// do a sanity check, have we already persisted this record?
            if (!ValidationSettings.AllowDuplicateRecords)
            {
                var duplicateQuery = new QueryEvent();
                duplicateQuery.Add((storageData as ICloneable).Clone() as HealthServiceRecordContainer, "SUBJ", HealthServiceRecordSiteRoleType.SubjectOf, null);
                duplicateQuery.Add(new QueryParameters()
                {
                    MatchStrength     = Core.ComponentModel.MatchStrength.Exact,
                    MatchingAlgorithm = MatchAlgorithm.Exact
                }, "FLT", HealthServiceRecordSiteRoleType.FilterOf, null);
                var storedRecords = QueryRecord(duplicateQuery as IComponent);
                if (storedRecords.Length != 0)
                {
                    throw new DuplicateNameException(ApplicationContext.LocaleService.GetString("DTPE004"));
                }
            }

            // Get the persister
            IComponentPersister persister = GetPersister(storageData.GetType());

            if (persister != null)
            {
                IDbTransaction tx   = null;
                IDbConnection  conn = null;
                try
                {
                    conn = DatabasePersistenceService.ConnectionManager.GetConnection();
                    tx   = conn.BeginTransaction();

                    var retVal = persister.Persist(conn, tx, storageData as IComponent, false);

                    // Set the mode
                    if (m_configuration.OverridePersistenceMode.HasValue)
                    {
                        mode = m_configuration.OverridePersistenceMode.Value;
                    }

                    // Commit or rollback
                    if (mode == DataPersistenceMode.Production)
                    {
                        tx.Commit();
                        tx = null;

                        // Notify that reconciliation is required and mark merge candidates
                        if (pid.Count() > 0)
                        {
                            this.m_clientRegistryMerge.MarkConflicts(retVal, pid);
                            if (this.m_notificationService != null && pid.Count() != 0)
                            {
                                var list = new List <VersionedDomainIdentifier>(pid)
                                {
                                    retVal
                                };
                                this.m_notificationService.NotifyReconciliationRequired(list);
                            }
                        }
                        else if (this.m_clientRegistryMerge != null)
                        {
                            this.m_threadPool.QueueUserWorkItem(this.MarkConflictsAsync, retVal);
                        }

                        // Notify register
                        if (this.m_notificationService != null && storageData is RegistrationEvent)
                        {
                            this.m_notificationService.NotifyRegister(storageData as RegistrationEvent);
                        }
                    }
                    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));
            }
        }