Exemple #1
0
        /// <summary>
        /// Get the register
        /// </summary>
        internal static IQueryComponentPersister GetQueryPersister(Type forType)
        {
            IComponentPersister pPersister = null;

            if (m_persisters.TryGetValue(forType, out pPersister))
            {
                return(pPersister as IQueryComponentPersister);
            }
#if DEBUG
            Trace.TraceError("Can't find register for '{0}'", forType);
#endif
            return(null);
        }
Exemple #2
0
        /// <summary>
        /// Get the persister for the specified type
        /// </summary>
        internal static IComponentPersister GetPersister(Type forType)
        {
            IComponentPersister pPersister = null;

            if (m_persisters.TryGetValue(forType, out pPersister))
            {
                return(pPersister);
            }
#if DEBUG
            Trace.TraceWarning("Can't find a persister for '{0}'", forType);
#endif
            return(null);
        }
Exemple #3
0
 /// <summary>
 /// Persist the components of the specified container
 /// </summary>
 public static void PersistComponents(IDbConnection conn, IDbTransaction tx, bool isUpdate, IComponentPersister persister, IContainer cont)
 {
     // Now time for sub-components
     foreach (IComponent cmp in cont.Components)
     {
         IComponentPersister cmpp = DatabasePersistenceService.GetPersister(cmp.GetType());
         if (cmpp != null)
         {
             var vid = cmpp.Persist(conn, tx, cmp, isUpdate);
             // Add this component to the registered components?
             if (vid != null)
             {
                 RegisterComponent(conn, tx, Decimal.Parse(vid.Identifier), cmp, (cmp.Site.Container as HealthServiceRecordContainer).Id, cmp.Site.Container);
             }
         }
         else
         {
             throw new InvalidOperationException(String.Format("Cannot find persister for '{0}'", cmp.GetType().FullName));
         }
     }
 }
Exemple #4
0
        /// <summary>
        /// Static constructor for this persistence service
        /// </summary>
        static DatabasePersistenceService()
        {
            m_configuration = ConfigurationManager.GetSection("marc.hi.ehrs.cr.persistence.data") as ConfigurationSectionHandler;
            m_persisters    = new Dictionary <Type, IComponentPersister>();

            // Verify that the database can be used
            foreach (var cm in new ConnectionManager[] { m_configuration.ConnectionManager, m_configuration.ReadonlyConnectionManager })
            {
                var conn = cm.GetConnection();
                try
                {
                    var dbVer = DbUtil.GetSchemaVersion(conn);
                    if (dbVer.CompareTo(typeof(DatabasePersistenceService).Assembly.GetName().Version) < 0)
                    {
                        throw new DataException(String.Format("The schema version '{0}' is less than the expected version of '{1}'",
                                                              dbVer, typeof(DatabasePersistenceService).Assembly.GetName().Version));
                    }
                    else
                    {
                        Trace.TraceInformation("Using Client Registry Schem Version '{0}'", dbVer);
                    }
                }
                finally
                {
                    conn.Close();
                }
            }

            // Scan this assembly for helpers
            Type[] persistenceTypes = Array.FindAll <Type>(typeof(DatabasePersistenceService).Assembly.GetTypes(), o => o.GetInterface(typeof(IComponentPersister).FullName) != null);


            // Persistence helpers
            foreach (var t in persistenceTypes)
            {
                ConstructorInfo     ci       = t.GetConstructor(Type.EmptyTypes);
                IComponentPersister instance = ci.Invoke(null) as IComponentPersister;
                m_persisters.Add(instance.HandlesComponent, instance);
            }
        }
Exemple #5
0
        /// <summary>
        /// De-Persist components
        /// </summary>
        public static void DePersistComponents(IDbConnection conn, IContainer cont, IComponentPersister parent, bool loadFast)
        {
            List <ComponentData> tComponents = GetComponents(conn, cont, false);

            // Include Inverse roles?
            if (cont is RegistrationEvent)
            {
                tComponents.AddRange(GetComponents(conn, new HealthServiceRecordComponentRef()
                {
                    Id = (cont as RegistrationEvent).Id
                }, true));
            }

            // Reconstruct components
            foreach (var cmp in tComponents)
            {
#if PERFMON
                Trace.TraceInformation("{0} : {1}", DateTime.Now.ToString("HH:mm:ss.ffff"), cmp.m_roleType.ToString());
#endif
                IComponentPersister cmpp = DatabasePersistenceService.GetPersister(cmp.m_componentType);
                if (cmpp != null)
                {
                    // Determine if we've already de-persisted the object
                    HealthServiceRecordComponent dcComp = m_alreadyDepersisted.Find(o => o != null && o.GetType().Equals(cmp.m_componentType) && o is IIdentifiable && (o as IIdentifiable).Identifier == cmp.m_componentId && (cmp.m_componentVersionId == default(Decimal) || (o as IIdentifiable).VersionIdentifier == cmp.m_componentVersionId));
                    //Trace.TraceInformation("DePersist {0}:{1}", cmp.m_componentType, cmp.m_componentId);
                    if (dcComp != null)
                    {
                        dcComp = dcComp.Clone() as HealthServiceRecordComponent;
                    }
                    else
                    {
                        if (cmpp is IVersionComponentPersister)
                        {
                            dcComp = (cmpp as IVersionComponentPersister).DePersist(conn, cmp.m_componentId, cmp.m_componentVersionId, cont, cmp.m_roleType, loadFast) as HealthServiceRecordComponent;
                        }
                        else
                        {
                            dcComp = cmpp.DePersist(conn, cmp.m_componentId, cont, cmp.m_roleType, loadFast) as HealthServiceRecordComponent;
                        }
                        if (dcComp != null)
                        {
                            m_alreadyDepersisted.Add(dcComp);
                        }
                    }

                    // Add to the graph
                    if (dcComp != null && dcComp.Site != null)
                    {
                        (dcComp.Site as HealthServiceRecordSite).SiteRoleType = cmp.m_roleType;
                    }
                    else if (dcComp != null)
                    {
                        (cont as HealthServiceRecordContainer).Add(dcComp, Guid.NewGuid().ToString(), cmp.m_roleType, null);
                    }
                }
                else
                {
                    throw new InvalidOperationException(String.Format("Cannot find persister for '{0}'", cmp.m_componentType.FullName));
                }
#if PERFMON
                Trace.TraceInformation("EO {0} : {1}", DateTime.Now.ToString("HH:mm:ss.ffff"), cmp.m_roleType.ToString());
#endif
            }
        }
Exemple #6
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));
            }
        }
Exemple #7
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));
            }
        }