Example #1
0
        /// <summary>
        /// Insert the specified sbadm
        /// </summary>
        public override Core.Model.Acts.SubstanceAdministration InsertInternal(DataContext context, Core.Model.Acts.SubstanceAdministration data, IPrincipal principal)
        {
            if (data.DoseUnit != null)
            {
                data.DoseUnit = data.DoseUnit?.EnsureExists(context, principal) as Concept;
            }
            if (data.Route != null)
            {
                data.Route = data.Route?.EnsureExists(context, principal) as Concept;
            }
            else if (!data.RouteKey.HasValue)
            {
                data.RouteKey = NullReasonKeys.NoInformation;
            }

            // JF: Correct dose unit key
            if (AdoPersistenceService.GetConfiguration().DataCorrectionKeys.Contains("invalid-sbadm-dose-unit") &&
                data.DoseUnitKey == Guid.Parse("a77b8d83-1cc9-4806-a268-5d1738154afa"))
            {
                data.DoseUnitKey = Guid.Parse("a4fc5c93-31c2-4f87-990e-c5a4e5ea2e76");
            }
            data.DoseUnitKey = data.DoseUnit?.Key ?? data.DoseUnitKey;
            data.RouteKey    = data.Route?.Key ?? data.RouteKey;
            return(base.InsertInternal(context, data, principal));
        }
        /// <summary>
        /// Represents as a model instance
        /// </summary>
        public override ActParticipation ToModelInstance(object dataInstance, DataContext context, IPrincipal principal)
        {
            if (dataInstance == null)
            {
                return(null);
            }

            var participationPart = dataInstance as DbActParticipation;
            var retVal            = new ActParticipation()
            {
                EffectiveVersionSequenceId = participationPart.EffectiveVersionSequenceId,
                ObsoleteVersionSequenceId  = participationPart.ObsoleteVersionSequenceId,
                ActKey               = participationPart.SourceKey,
                PlayerEntityKey      = participationPart.TargetKey,
                ParticipationRoleKey = participationPart.ParticipationRoleKey,
                LoadState            = context.LoadState,
                Quantity             = participationPart.Quantity,
                Key             = participationPart.Key,
                SourceEntityKey = participationPart.SourceKey
            };

            if (context.LoadState == Core.Model.LoadState.FullLoad)
            {
                var concept = AdoPersistenceService.GetPersister(typeof(Concept)).Get(participationPart.ParticipationRoleKey);
                if (concept != null)
                {
                    retVal.ParticipationRole = concept as Concept;
                }
            }

            return(retVal);
        }
        /// <summary>
        /// Get the specified object
        /// </summary>
        internal override TModel Get(DataContext context, Guid key, IPrincipal principal)
        {
            // We need to join, but to what?
            // True to get the cache item
            var cacheService = new AdoPersistenceCache(context);
            var cacheItem    = cacheService?.GetCacheItem <TModel>(key) as TModel;

            if (cacheItem != null && context.Transaction == null)
            {
                if (cacheItem.LoadState < context.LoadState)
                {
                    cacheItem.LoadAssociations(context, principal);
                    cacheService?.Add(cacheItem);
                }
                return(cacheItem);
            }
            else
            {
                var domainQuery = AdoPersistenceService.GetQueryBuilder().CreateQuery <TModel>(o => o.Key == key && o.ObsoletionTime == null).Build();
                domainQuery.OrderBy <TRootEntity>(o => o.VersionSequenceId, Core.Model.Map.SortOrderType.OrderByDescending);
                cacheItem = this.ToModelInstance(context.FirstOrDefault <TQueryReturn>(domainQuery), context, principal);
                if (cacheService != null)
                {
                    cacheService.Add(cacheItem);
                }
                return(cacheItem);
            }
        }
        /// <summary>
        /// Performs the actual query
        /// </summary>
        public override IEnumerable <TModel> QueryInternal(DataContext context, Expression <Func <TModel, bool> > query, Guid queryId, int offset, int?count, out int totalResults, IPrincipal principal, bool countResults = true)
        {
            int resultCount = 0;
            var results     = this.QueryInternal(context, query, queryId, offset, count, out resultCount, countResults).ToList();

            totalResults = resultCount;

            if (!AdoPersistenceService.GetConfiguration().SingleThreadFetch)
            {
                return(results.AsParallel().Select(o =>
                {
                    var subContext = context;
                    var newSubContext = results.Count() > 1;

                    try
                    {
                        if (newSubContext)
                        {
                            subContext = subContext.OpenClonedContext();
                        }

                        if (o is Guid)
                        {
                            return this.Get(subContext, (Guid)o, principal);
                        }
                        else
                        {
                            return this.CacheConvert(o, subContext, principal);
                        }
                    }
                    catch (Exception e)
                    {
                        this.m_tracer.TraceEvent(TraceEventType.Error, e.HResult, "Error performing sub-query: {0}", e);
                        throw;
                    }
                    finally
                    {
                        if (newSubContext)
                        {
                            subContext.Dispose();
                        }
                    }
                }));
            }
            else
            {
                return(results.Select(o =>
                {
                    if (o is Guid)
                    {
                        return this.Get(context, (Guid)o, principal);
                    }
                    else
                    {
                        return this.CacheConvert(o, context, principal);
                    }
                }));
            }
        }
        /// <summary>
        /// Insert or update contents of the bundle
        /// </summary>
        /// <returns></returns>
        public override Bundle InsertInternal(DataContext context, Bundle data, IPrincipal principal)
        {
            if (data.Item == null)
            {
                return(data);
            }
            this.m_tracer.TraceInformation("Bundle has {0} objects...", data.Item.Count);
            data = this.ReorganizeForInsert(data);
            this.m_tracer.TraceInformation("After reorganization has {0} objects...", data.Item.Count);

            if (AdoPersistenceService.GetConfiguration().PrepareStatements)
            {
                context.PrepareStatements = true;
            }
            for (int i = 0; i < data.Item.Count; i++)
            {
                var itm    = data.Item[i];
                var idp    = typeof(IDataPersistenceService <>).MakeGenericType(new Type[] { itm.GetType() });
                var svc    = ApplicationContext.Current.GetService(idp);
                var method = "Insert";

                if (itm.TryGetExisting(context, principal, true) != null)
                {
                    method = "Update";
                }

                this.m_tracer.TraceInformation("Will {0} object from bundle {1}...", method, itm);
                this.ProgressChanged?.Invoke(this, new ProgressChangedEventArgs((float)(i + 1) / data.Item.Count, itm));

                var mi = svc.GetType().GetRuntimeMethod(method, new Type[] { typeof(DataContext), itm.GetType(), typeof(IPrincipal) });
                try
                {
                    data.Item[i] = mi.Invoke(svc, new object[] { context, itm, principal }) as IdentifiedData;
                }
                catch (TargetInvocationException e)
                {
                    throw e.InnerException;
                }
            }

            // Cache items
            foreach (var itm in data.Item)
            {
                itm.LoadState = LoadState.FullLoad;
                context.AddCacheCommit(itm);
            }
            return(data);
        }
        /// <summary>
        /// Perform the query
        /// </summary>
        protected virtual IEnumerable <Object> QueryInternal(DataContext context, Expression <Func <TModel, bool> > query, Guid queryId, int offset, int?count, out int totalResults, bool incudeCount = true)
        {
#if DEBUG
            Stopwatch sw = new Stopwatch();
            sw.Start();
#endif

            SqlStatement domainQuery = null;
            try
            {
                // Query has been registered?
                if (queryId != Guid.Empty && this.m_queryPersistence?.IsRegistered(queryId.ToString()) == true)
                {
                    totalResults = (int)this.m_queryPersistence.QueryResultTotalQuantity(queryId.ToString());
                    var resultKeys = this.m_queryPersistence.GetQueryResults <Guid>(queryId.ToString(), offset, count.Value);
                    return(resultKeys.Select(p => p.Id).OfType <Object>());
                }

                // Is obsoletion time already specified?
                if (!query.ToString().Contains("ObsoletionTime") && typeof(BaseEntityData).IsAssignableFrom(typeof(TModel)))
                {
                    var obsoletionReference = Expression.MakeBinary(ExpressionType.Equal, Expression.MakeMemberAccess(query.Parameters[0], typeof(TModel).GetProperty(nameof(BaseEntityData.ObsoletionTime))), Expression.Constant(null));
                    query = Expression.Lambda <Func <TModel, bool> >(Expression.MakeBinary(ExpressionType.AndAlso, obsoletionReference, query.Body), query.Parameters);
                }

                // Domain query
                domainQuery = context.CreateSqlStatement <TDomain>().SelectFrom();
                var expression = m_mapper.MapModelExpression <TModel, TDomain>(query, false);
                if (expression != null)
                {
                    Type lastJoined = typeof(TDomain);
                    if (typeof(CompositeResult).IsAssignableFrom(typeof(TQueryReturn)))
                    {
                        foreach (var p in typeof(TQueryReturn).GenericTypeArguments.Select(o => AdoPersistenceService.GetMapper().MapModelType(o)))
                        {
                            if (p != typeof(TDomain))
                            {
                                // Find the FK to join
                                domainQuery.InnerJoin(lastJoined, p);
                                lastJoined = p;
                            }
                        }
                    }

                    domainQuery.Where <TDomain>(expression);
                }
                else
                {
                    m_tracer.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "Will use slow query construction due to complex mapped fields");
                    domainQuery = AdoPersistenceService.GetQueryBuilder().CreateQuery(query);
                }

                // Count = 0 means we're not actually fetching anything so just hit the db
                if (count != 0)
                {
                    domainQuery = this.AppendOrderBy(domainQuery);

                    // Query id just get the UUIDs in the db
                    if (queryId != Guid.Empty && count != 0)
                    {
                        ColumnMapping pkColumn = null;
                        if (typeof(CompositeResult).IsAssignableFrom(typeof(TQueryReturn)))
                        {
                            foreach (var p in typeof(TQueryReturn).GenericTypeArguments.Select(o => AdoPersistenceService.GetMapper().MapModelType(o)))
                            {
                                if (!typeof(DbSubTable).IsAssignableFrom(p) && !typeof(IDbVersionedData).IsAssignableFrom(p))
                                {
                                    pkColumn = TableMapping.Get(p).Columns.SingleOrDefault(o => o.IsPrimaryKey);
                                    break;
                                }
                            }
                        }
                        else
                        {
                            pkColumn = TableMapping.Get(typeof(TQueryReturn)).Columns.SingleOrDefault(o => o.IsPrimaryKey);
                        }

                        var keyQuery = AdoPersistenceService.GetQueryBuilder().CreateQuery(query, pkColumn).Build();

                        var resultKeys = context.Query <Guid>(keyQuery.Build());

                        //ApplicationContext.Current.GetService<IThreadPoolService>().QueueNonPooledWorkItem(a => this.m_queryPersistence?.RegisterQuerySet(queryId.ToString(), resultKeys.Select(o => new Identifier<Guid>(o)).ToArray(), query), null);
                        // Another check
                        this.m_queryPersistence?.RegisterQuerySet(queryId.ToString(), resultKeys.Count(), resultKeys.Select(o => new Identifier <Guid>(o)).Take(1000).ToArray(), query);

                        ApplicationContext.Current.GetService <IThreadPoolService>().QueueNonPooledWorkItem(o =>
                        {
                            int ofs   = 1000;
                            var rkeys = o as Guid[];
                            while (ofs < rkeys.Length)
                            {
                                this.m_queryPersistence?.AddResults(queryId.ToString(), rkeys.Skip(ofs).Take(1000).Select(k => new Identifier <Guid>(k)).ToArray());
                                ofs += 1000;
                            }
                        }, resultKeys.ToArray());

                        if (incudeCount)
                        {
                            totalResults = (int)resultKeys.Count();
                        }
                        else
                        {
                            totalResults = 0;
                        }

                        var retVal = resultKeys.Skip(offset);
                        if (count.HasValue)
                        {
                            retVal = retVal.Take(count.Value);
                        }
                        return(retVal.OfType <Object>());
                    }
                    else if (incudeCount)
                    {
                        totalResults = context.Count(domainQuery);
                        if (totalResults == 0)
                        {
                            return(new List <Object>());
                        }
                    }
                    else
                    {
                        totalResults = 0;
                    }

                    if (offset > 0)
                    {
                        domainQuery.Offset(offset);
                    }
                    if (count.HasValue)
                    {
                        domainQuery.Limit(count.Value);
                    }

                    return(this.DomainQueryInternal <TQueryReturn>(context, domainQuery, ref totalResults).OfType <Object>());
                }
                else
                {
                    totalResults = context.Count(domainQuery);
                    return(new List <Object>());
                }
            }
            catch (Exception ex)
            {
                if (domainQuery != null)
                {
                    this.m_tracer.TraceEvent(TraceEventType.Error, ex.HResult, context.GetQueryLiteral(domainQuery.Build()));
                }
                context.Dispose(); // No longer important

                throw;
            }
#if DEBUG
            finally
            {
                sw.Stop();
            }
#endif
        }
        /// <summary>
        /// Reorganize all the major items for insert
        /// </summary>
        private Bundle ReorganizeForInsert(Bundle bundle)
        {
            Bundle retVal = new Bundle()
            {
                Item = new List <IdentifiedData>()
            };

            foreach (var itm in bundle.Item.Where(o => o != null))
            {
                this.m_tracer.TraceInformation("Reorganizing {0}..", itm.Key);
                // Are there any relationships
                if (itm is Entity)
                {
                    var ent = itm as Entity;
                    foreach (var rel in ent.Relationships)
                    {
                        this.m_tracer.TraceInformation("Processing {0} / relationship / {1} ..", itm.Key, rel.TargetEntityKey);

                        var bitm = bundle.Item.FirstOrDefault(o => o.Key == rel.TargetEntityKey);
                        if (bitm == null)
                        {
                            continue;
                        }

                        if (retVal.Item.Any(o => o.Key == rel.TargetEntityKey))
                        {
                            continue;
                        }
                        this.m_tracer.TraceInformation("Bumping (due to relationship): {0}", bitm);

                        retVal.Item.Add(bitm); // make sure it gets inserted first
                    }
                }
                else if (itm is Act)
                {
                    var act = itm as Act;
                    foreach (var rel in act.Relationships)
                    {
                        this.m_tracer.TraceInformation("Processing {0} / relationship / {1} ..", itm.Key, rel.TargetActKey);
                        var bitm = bundle.Item?.FirstOrDefault(o => o.Key == rel?.TargetActKey);
                        if (bitm == null)
                        {
                            continue;
                        }

                        if (retVal.Item.Any(o => o.Key == rel.TargetActKey))
                        {
                            continue;
                        }
                        this.m_tracer.TraceInformation("Bumping (due to relationship): {0}", bitm);
                        retVal.Item.Add(bitm); // make sure it gets inserted first
                    }

                    foreach (var rel in act.Participations)
                    {
                        this.m_tracer.TraceInformation("Processing {0} / participation / {1} ..", itm.Key, rel.PlayerEntityKey);
                        var bitm = bundle.Item?.FirstOrDefault(o => o.Key == rel?.PlayerEntityKey);
                        if (bitm == null)
                        {
                            continue;
                        }

                        if (retVal.Item.Any(o => o.Key == rel.PlayerEntityKey))
                        {
                            continue;
                        }

                        this.m_tracer.TraceInformation("Bumping (due to participation): {0}", bitm);
                        retVal.Item.Add(bitm); // make sure it gets inserted first
                    }


                    // Old versions of the mobile had an issue with missing record targets
                    if (AdoPersistenceService.GetConfiguration().DataCorrectionKeys.Contains("correct-missing-rct"))
                    {
                        var patientEncounter = bundle.Item.OfType <PatientEncounter>().FirstOrDefault();

                        if (patientEncounter != null)
                        {
                            var rct = act.Participations.FirstOrDefault(o => o.ParticipationRoleKey == OpenIZ.Core.Model.Constants.ActParticipationKey.RecordTarget);
                            if (!(rct == null || rct.PlayerEntityKey.HasValue))
                            {
                                var perct = patientEncounter.Participations.FirstOrDefault(o => o.ParticipationRoleKey == ActParticipationKey.RecordTarget);

                                act.Participations.Remove(rct);
                                act.Participations.Add(new ActParticipation(ActParticipationKey.RecordTarget, perct.PlayerEntityKey));
                            }
                        }
                    }
                }

                this.m_tracer.TraceInformation("Re-adding: {0}", itm);
                retVal.Item.Add(itm);
            }

            return(retVal);
        }
Example #8
0
        /// <summary>
        /// Query internal
        /// </summary>
        protected override IEnumerable <Object> QueryInternal(DataContext context, Expression <Func <TModel, bool> > query, Guid queryId, int offset, int?count, out int totalResults, bool countResults = true)
        {
            // Is obsoletion time already specified?
            if (!query.ToString().Contains("ObsoletionTime"))
            {
                var obsoletionReference = Expression.MakeBinary(ExpressionType.Equal, Expression.MakeMemberAccess(query.Parameters[0], typeof(TModel).GetProperty(nameof(BaseEntityData.ObsoletionTime))), Expression.Constant(null));
                query = Expression.Lambda <Func <TModel, bool> >(Expression.MakeBinary(ExpressionType.AndAlso, obsoletionReference, query.Body), query.Parameters);
            }

            // Query has been registered?
            if (this.m_queryPersistence?.IsRegistered(queryId.ToString()) == true)
            {
                totalResults = (int)this.m_queryPersistence.QueryResultTotalQuantity(queryId.ToString());
                var keyResults = this.m_queryPersistence.GetQueryResults <Guid>(queryId.ToString(), offset, count.Value);
                return(keyResults.Select(p => p.Id).OfType <Object>());
            }

            SqlStatement domainQuery = null;

            try
            {
                domainQuery = context.CreateSqlStatement <TDomain>().SelectFrom()
                              .InnerJoin <TDomain, TDomainKey>(o => o.Key, o => o.Key)
                              .Where <TDomain>(m_mapper.MapModelExpression <TModel, TDomain>(query)).Build();
            }
            catch (Exception e)
            {
                m_tracer.TraceEvent(System.Diagnostics.TraceEventType.Verbose, e.HResult, "Will use slow query construction due to {0}", e.Message);
                domainQuery = AdoPersistenceService.GetQueryBuilder().CreateQuery(query).Build();
            }

            domainQuery = this.AppendOrderBy(domainQuery);


            // Query id just get the UUIDs in the db
            if (queryId != Guid.Empty)
            {
                ColumnMapping pkColumn = TableMapping.Get(typeof(TDomainKey)).Columns.SingleOrDefault(o => o.IsPrimaryKey);

                var keyQuery   = AdoPersistenceService.GetQueryBuilder().CreateQuery(query, pkColumn).Build();
                var resultKeys = context.Query <Guid>(keyQuery.Build());
                this.m_queryPersistence?.RegisterQuerySet(queryId.ToString(), resultKeys.Count(), resultKeys.Take(1000).Select(o => new Identifier <Guid>(o)).ToArray(), query);

                ApplicationContext.Current.GetService <IThreadPoolService>().QueueNonPooledWorkItem(o =>
                {
                    int ofs   = 1000;
                    var rkeys = o as Guid[];
                    if (rkeys == null)
                    {
                        return;
                    }
                    while (ofs < rkeys.Length)
                    {
                        this.m_queryPersistence?.AddResults(queryId.ToString(), rkeys.Skip(ofs).Take(1000).Select(k => new Identifier <Guid>(k)).ToArray());
                        ofs += 1000;
                    }
                }, resultKeys.ToArray());

                if (countResults)
                {
                    totalResults = (int)resultKeys.Count();
                }
                else
                {
                    totalResults = 0;
                }

                var retVal = resultKeys.Skip(offset);
                if (count.HasValue)
                {
                    retVal = retVal.Take(count.Value);
                }
                return(retVal.OfType <Object>());
            }
            else if (countResults)
            {
                totalResults = context.Count(domainQuery);
                if (totalResults == 0)
                {
                    return(new List <CompositeResult <TDomain, TDomainKey> >());
                }
            }
            else
            {
                totalResults = 0;
            }

            if (offset > 0)
            {
                domainQuery.Offset(offset);
            }
            if (count.HasValue)
            {
                domainQuery.Limit(count.Value);
            }
            return(context.Query <CompositeResult <TDomain, TDomainKey> >(domainQuery).OfType <Object>());
        }
Example #9
0
        /// <summary>
        /// Represents as a model instance
        /// </summary>
        public override EntityRelationship ToModelInstance(object dataInstance, DataContext context, IPrincipal principal)
        {
            if (dataInstance == null)
            {
                return(null);
            }

            var entPart = dataInstance as DbEntityRelationship;

            return(new EntityRelationship()
            {
                EffectiveVersionSequenceId = entPart.EffectiveVersionSequenceId,
                ObsoleteVersionSequenceId = entPart.ObsoleteVersionSequenceId,
                HolderKey = entPart.SourceKey,
                TargetEntityKey = entPart.TargetKey,
                RelationshipType = context.LoadState == Core.Model.LoadState.FullLoad ?  AdoPersistenceService.GetPersister(typeof(Concept)).Get(entPart.RelationshipTypeKey) as Concept : null,
                RelationshipTypeKey = entPart.RelationshipTypeKey,
                Quantity = entPart.Quantity,
                LoadState = context.LoadState,
                Key = entPart.Key,
                SourceEntityKey = entPart.SourceKey
            });
        }
Example #10
0
 /// <summary>
 /// Bundle persistence
 /// </summary>
 public AuditBundlePersistenceService()
 {
     this.m_persistenceService = ApplicationServiceContext.Current.GetService <AdoPersistenceService>();
 }
Example #11
0
        /// <summary>
        /// Try get by classifier
        /// </summary>
        public static IIdentifiedEntity TryGetExisting(this IIdentifiedEntity me, DataContext context, IPrincipal principal, bool forceDatabase = false)
        {
            // Is there a classifier?
            var idpInstance  = AdoPersistenceService.GetPersister(me.GetType()) as IAdoPersistenceService;
            var cacheService = new AdoPersistenceCache(context);

            IIdentifiedEntity existing = null;

            // Forcing from database load from
            if (forceDatabase && me.Key.HasValue)
            {
                // HACK: This should really hit the database instead of just clearing the cache
                ApplicationContext.Current.GetService <IDataCachingService>()?.Remove(me.Key.Value);
            }
            //var tableType = AdoPersistenceService.GetMapper().MapModelType(me.GetType());
            //if (me.GetType() != tableType)
            //{
            //    var tableMap = TableMapping.Get(tableType);
            //    var dbExisting = context.FirstOrDefault(tableType, context.CreateSqlStatement().SelectFrom(tableType).Where($"{tableMap.Columns.FirstOrDefault(o=>o.IsPrimaryKey).Name}=?", me.Key.Value));
            //    if (dbExisting != null)
            //        existing = idpInstance.ToModelInstance(dbExisting, context, principal) as IIdentifiedEntity;
            //}
            if (me.Key != Guid.Empty && me.Key != null)
            {
                existing = idpInstance.Get(context, me.Key.Value, principal) as IIdentifiedEntity;
            }

            var classAtt = me.GetType().GetCustomAttribute <KeyLookupAttribute>();

            if (classAtt != null && existing == null)
            {
                // Get the domain type
                var dataType = AdoPersistenceService.GetMapper().MapModelType(me.GetType());
                var tableMap = TableMapping.Get(dataType);

                // Get the classifier attribute value
                var    classProperty   = me.GetType().GetProperty(classAtt.UniqueProperty);
                object classifierValue = classProperty.GetValue(me); // Get the classifier

                // Is the classifier a UUID'd item?
                if (classifierValue is IIdentifiedEntity)
                {
                    classifierValue = (classifierValue as IIdentifiedEntity).Key.Value;
                    classProperty   = me.GetType().GetProperty(classProperty.GetCustomAttribute <SerializationReferenceAttribute>()?.RedirectProperty ?? classProperty.Name);
                }

                // Column
                var column = tableMap.GetColumn(AdoPersistenceService.GetMapper().MapModelProperty(me.GetType(), dataType, classProperty));
                // Now we want to query
                SqlStatement stmt = context.CreateSqlStatement().SelectFrom(dataType)
                                    .Where($"{column.Name} = ?", classifierValue);

                Guid          objIdCache = Guid.Empty;
                IDbIdentified dataObject = null;

                // We've seen this before

                String classKey = $"{dataType}.{classifierValue}";
                if (m_classIdCache.TryGetValue(classKey, out objIdCache))
                {
                    existing = cacheService?.GetCacheItem(objIdCache) as IdentifiedData;
                }
                if (existing == null)
                {
                    dataObject = context.FirstOrDefault(dataType, stmt) as IDbIdentified;
                    if (dataObject != null)
                    {
                        lock (m_classIdCache)
                            if (!m_classIdCache.ContainsKey(classKey))
                            {
                                m_classIdCache.Add(classKey, dataObject.Key);
                            }
                        var existCache = cacheService?.GetCacheItem((dataObject as IDbIdentified).Key);
                        if (existCache != null)
                        {
                            existing = existCache as IdentifiedData;
                        }
                        else
                        {
                            existing = idpInstance.ToModelInstance(dataObject, context, principal) as IIdentifiedEntity;
                        }
                    }
                }
            }

            return(existing);
        }
Example #12
0
        /// <summary>
        /// This method will load all basic properties for the specified model object
        /// </summary>
        public static void LoadAssociations <TModel>(this TModel me, DataContext context, IPrincipal principal, params String[] loadProperties) where TModel : IIdentifiedEntity
        {
            // I duz not haz a chzbrgr?
            if (me == null || me.LoadState >= context.LoadState)
            {
                return;
            }
            else if (context.Transaction != null) // kk.. I haz a transaction
            {
                return;
            }

#if DEBUG
            /*
             * Me neez all the timez
             *
             * /\_/\
             * >^.^<.---.
             * _'-`-'     )\
             * (6--\ |--\ (`.`-.
             *   --'  --'  ``-'
             */
            Stopwatch sw = new Stopwatch();
            sw.Start();
#endif

            // Cache get classification property - thiz makez us fasters
            PropertyInfo classProperty = null;
            if (!s_classificationProperties.TryGetValue(typeof(TModel), out classProperty))
            {
                classProperty = typeof(TModel).GetRuntimeProperty(typeof(TModel).GetTypeInfo().GetCustomAttribute <ClassifierAttribute>()?.ClassifierProperty ?? "____XXX");
                if (classProperty != null)
                {
                    classProperty = typeof(TModel).GetRuntimeProperty(classProperty.GetCustomAttribute <SerializationReferenceAttribute>()?.RedirectProperty ?? classProperty.Name);
                }
                lock (s_lockObject)
                    if (!s_classificationProperties.ContainsKey(typeof(TModel)))
                    {
                        s_classificationProperties.Add(typeof(TModel), classProperty);
                    }
            }

            // Classification property?
            String classValue = classProperty?.GetValue(me)?.ToString();

            // Cache the props so future kitties can call it
            IEnumerable <PropertyInfo> properties = null;
            var propertyCacheKey = $"{me.GetType()}.FullName[{classValue}]";
            if (!s_runtimeProperties.TryGetValue(propertyCacheKey, out properties))
            {
                lock (s_runtimeProperties)
                {
                    properties = me.GetType().GetRuntimeProperties().Where(o => o.GetCustomAttribute <DataIgnoreAttribute>() == null && o.GetCustomAttributes <AutoLoadAttribute>().Any(p => p.ClassCode == classValue || p.ClassCode == null) && typeof(IdentifiedData).IsAssignableFrom(o.PropertyType.StripGeneric())).ToList();

                    if (!s_runtimeProperties.ContainsKey(propertyCacheKey))
                    {
                        s_runtimeProperties.Add(propertyCacheKey, properties);
                    }
                }
            }

            // Load fast or lean mode only root associations which will appear on the wire
            if (context.LoadState == LoadState.PartialLoad)
            {
                if (me.LoadState == LoadState.PartialLoad) // already partially loaded :/
                {
                    return;
                }
                else
                {
                    me.LoadState = LoadState.PartialLoad;
                    properties   = properties.Where(o => o.GetCustomAttribute <XmlAttributeAttribute>() != null || o.GetCustomAttribute <XmlElementAttribute>() != null).ToList();
                }
            }

            // Iterate over the properties and load the properties
            foreach (var pi in properties)
            {
                if (loadProperties.Length > 0 &&
                    !loadProperties.Contains(pi.Name))
                {
                    continue;
                }

                // Map model type to domain
                var adoPersister = AdoPersistenceService.GetPersister(pi.PropertyType.StripGeneric());

                // Loading associations, so what is the associated type?
                if (typeof(IList).IsAssignableFrom(pi.PropertyType) &&
                    adoPersister is IAdoAssociativePersistenceService &&
                    me.Key.HasValue) // List so we select from the assoc table where we are the master table
                {
                    // Is there not a value?
                    var assocPersister = adoPersister as IAdoAssociativePersistenceService;

                    // We want to query based on our PK and version if applicable
                    decimal?        versionSequence = (me as IBaseEntityData)?.ObsoletionTime.HasValue == true ? (me as IVersionedEntity)?.VersionSequence : null;
                    var             assoc           = assocPersister.GetFromSource(context, me.Key.Value, versionSequence, principal);
                    ConstructorInfo ci = null;
                    if (!m_constructors.TryGetValue(pi.PropertyType, out ci))
                    {
                        var type = pi.PropertyType.StripGeneric();
                        while (type != typeof(Object) && ci == null)
                        {
                            ci   = pi.PropertyType.GetConstructor(new Type[] { typeof(IEnumerable <>).MakeGenericType(type) });
                            type = type.BaseType;
                        }
                        if (ci != null)
                        {
                            lock (s_lockObject)
                                if (!m_constructors.ContainsKey(pi.PropertyType))
                                {
                                    m_constructors.Add(pi.PropertyType, ci);
                                }
                        }
                        else
                        {
                            throw new InvalidOperationException($"This is odd, you seem to have a list with no constructor -> {pi.PropertyType}");
                        }
                    }
                    var listValue = ci.Invoke(new object[] { assoc });
                    pi.SetValue(me, listValue);
                }
                else if (typeof(IIdentifiedEntity).IsAssignableFrom(pi.PropertyType)) // Single
                {
                    // Single property, we want to execute a get on the key property
                    var pid = pi;
                    if (pid.Name.EndsWith("Xml")) // Xml purposes only
                    {
                        pid = pi.DeclaringType.GetProperty(pi.Name.Substring(0, pi.Name.Length - 3));
                    }
                    var redirectAtt = pid.GetCustomAttribute <SerializationReferenceAttribute>();

                    // We want to issue a query
                    var keyProperty = redirectAtt != null?pi.DeclaringType.GetProperty(redirectAtt.RedirectProperty) : pi.DeclaringType.GetProperty(pid.Name + "Key");

                    if (keyProperty == null)
                    {
                        continue;
                    }
                    var keyValue = keyProperty?.GetValue(me);
                    if (keyValue == null ||
                        Guid.Empty.Equals(keyValue))
                    {
                        continue; // No key specified
                    }
                    // This is kinda messy.. maybe iz to be changez
                    object value = null;
                    if (!context.Data.TryGetValue(keyValue.ToString(), out value))
                    {
                        value = adoPersister.Get(context, (Guid)keyValue, principal);
                        context.AddData(keyValue.ToString(), value);
                    }
                    pid.SetValue(me, value);
                }
            }
#if DEBUG
            sw.Stop();
            s_traceSource.TraceEvent(TraceEventType.Verbose, 0, "Load associations for {0} took {1} ms", me, sw.ElapsedMilliseconds);
#endif

            if (me.LoadState == LoadState.New)
            {
                me.LoadState = LoadState.FullLoad;
            }
        }
Example #13
0
        /// <summary>
        /// Ensures a model has been persisted
        /// </summary>
        public static IIdentifiedEntity EnsureExists(this IIdentifiedEntity me, DataContext context, IPrincipal principal)
        {
            if (me == null)
            {
                return(null);
            }

            // Me
            var    vMe  = me as IVersionedEntity;
            String dkey = String.Format("{0}.{1}", me.GetType().FullName, me.Key);

            IIdentifiedEntity existing = me.TryGetExisting(context, principal);
            var idpInstance            = AdoPersistenceService.GetPersister(me.GetType());

            // Don't touch the child just return reference
            if (!AdoPersistenceService.GetConfiguration().AutoInsertChildren)
            {
                if (existing != null)
                {
                    if (me.Key != existing.Key ||
                        vMe?.VersionKey != (existing as IVersionedEntity)?.VersionKey)
                    {
                        me.CopyObjectData(existing); // copy data into reference
                    }
                    return(existing);
                }
                else
                {
                    throw new KeyNotFoundException(me.Key.Value.ToString());
                }
            }

            // Existing exists?
            if (existing != null && me.Key.HasValue)
            {
                // Exists but is an old version
                if ((existing as IVersionedEntity)?.VersionKey != vMe?.VersionKey &&
                    vMe?.VersionKey != null && vMe?.VersionKey != Guid.Empty)
                {
                    // Update method
                    IVersionedEntity updated = idpInstance.Update(context, me, principal) as IVersionedEntity;
                    me.Key = updated.Key;
                    if (vMe != null)
                    {
                        vMe.VersionKey = (updated as IVersionedEntity).VersionKey;
                    }
                    return(updated);
                }
                return(existing);
            }
            else if (existing == null) // Insert
            {
                IIdentifiedEntity inserted = idpInstance.Insert(context, me, principal) as IIdentifiedEntity;
                me.Key = inserted.Key;

                if (vMe != null)
                {
                    vMe.VersionKey = (inserted as IVersionedEntity).VersionKey;
                }
                return(inserted);
            }
            return(existing);
        }
Example #14
0
        /// <summary>
        /// Update the specified data
        /// </summary>
        public Core.Model.Acts.Act UpdateCoreProperties(DataContext context, Core.Model.Acts.Act data, IPrincipal principal)
        {
            if (data.ClassConcept != null)
            {
                data.ClassConcept = data.ClassConcept?.EnsureExists(context, principal) as Concept;
            }
            if (data.MoodConcept != null)
            {
                data.MoodConcept = data.MoodConcept?.EnsureExists(context, principal) as Concept;
            }
            if (data.ReasonConcept != null)
            {
                data.ReasonConcept = data.ReasonConcept?.EnsureExists(context, principal) as Concept;
            }
            if (data.StatusConcept != null)
            {
                data.StatusConcept = data.StatusConcept?.EnsureExists(context, principal) as Concept;
            }
            if (data.TypeConcept != null)
            {
                data.TypeConcept = data.TypeConcept?.EnsureExists(context, principal) as Concept;
            }
            if (data.Template != null)
            {
                data.Template = data.Template?.EnsureExists(context, principal) as TemplateDefinition;
            }

            data.ClassConceptKey  = data.ClassConcept?.Key ?? data.ClassConceptKey;
            data.MoodConceptKey   = data.MoodConcept?.Key ?? data.MoodConceptKey;
            data.ReasonConceptKey = data.ReasonConcept?.Key ?? data.ReasonConceptKey;
            data.StatusConceptKey = data.StatusConcept?.Key ?? data.StatusConceptKey ?? StatusKeys.New;

            // Do the update
            var retVal = base.UpdateInternal(context, data, principal);

            if (data.Extensions != null)
            {
                base.UpdateVersionedAssociatedItems <Core.Model.DataTypes.ActExtension, DbActExtension>(
                    data.Extensions.Where(o => o != null && !o.IsEmpty()),
                    retVal,
                    context,
                    principal);
            }

            if (data.Identifiers != null)
            {
                base.UpdateVersionedAssociatedItems <Core.Model.DataTypes.ActIdentifier, DbActIdentifier>(
                    data.Identifiers.Where(o => o != null && !o.IsEmpty()),
                    retVal,
                    context,
                    principal);
            }

            if (data.Notes != null)
            {
                base.UpdateVersionedAssociatedItems <Core.Model.DataTypes.ActNote, DbActNote>(
                    data.Notes.Where(o => o != null && !o.IsEmpty()),
                    retVal,
                    context,
                    principal);
            }

            if (data.Participations != null)
            {
                // Correct mixed keys
                if (AdoPersistenceService.GetConfiguration().DataCorrectionKeys.Contains("edmonton-participation-keyfix"))
                {
                    // Obsolete all
                    foreach (var itm in context.Query <DbActParticipation>(o => o.SourceKey == retVal.Key && o.ObsoleteVersionSequenceId == null && o.ParticipationRoleKey == ActParticipationKey.Consumable))
                    {
                        itm.ObsoleteVersionSequenceId = retVal.VersionSequence;
                        context.Update(itm);
                    }
                    // Now we want to re-point to correct the issue
                    foreach (var itm in context.Query <DbActParticipation>(o => o.SourceKey == retVal.Key && o.ParticipationRoleKey == ActParticipationKey.Consumable && o.ObsoleteVersionSequenceId == retVal.VersionSequence))
                    {
                        var dItm = data.Participations.Find(o => o.Key == itm.Key);
                        if (dItm != null)
                        {
                            itm.TargetKey = dItm.PlayerEntityKey.Value;
                        }
                        itm.ObsoleteVersionSequenceId = null;
                        context.Update(itm);
                    }
                }

                // Update versioned association items
                base.UpdateVersionedAssociatedItems <Core.Model.Acts.ActParticipation, DbActParticipation>(
                    data.Participations.Where(o => o != null && !o.IsEmpty()),
                    retVal,
                    context,
                    principal);
            }

            if (data.Relationships != null)
            {
                base.UpdateVersionedAssociatedItems <Core.Model.Acts.ActRelationship, DbActRelationship>(
                    data.Relationships.Where(o => o != null && !o.IsEmpty() && (o.SourceEntityKey == data.Key || !o.SourceEntityKey.HasValue)),
                    retVal,
                    context,
                    principal);
            }

            if (data.Tags != null)
            {
                base.UpdateAssociatedItems <Core.Model.DataTypes.ActTag, DbActTag>(
                    data.Tags.Where(o => o != null && !o.IsEmpty()),
                    retVal,
                    context,
                    principal);
            }

            return(retVal);
        }