Example #1
0
        /// <summary>
        /// Insert or update contents of the bundle
        /// </summary>
        /// <returns></returns>
        public override AuditBundle InsertInternal(DataContext context, AuditBundle data, IPrincipal principal)
        {
            if (data.Item == null)
            {
                return(data);
            }
            this.m_tracer.TraceInfo("Audit Bundle has {0} objects...", data.Item.Count);

            for (int i = 0; i < data.Item.Count; i++)
            {
                var itm = data.Item[i];
                var svc = AdoAuditPersistenceService.GetPersister(itm.GetType());

                this.ProgressChanged?.Invoke(this, new ProgressChangedEventArgs((float)(i + 1) / data.Item.Count, itm));
                try
                {
                    if (svc == null)
                    {
                        throw new InvalidOperationException($"Cannot find persister for {itm.GetType()}");
                    }
                    if (itm.TryGetExisting(context, principal, true) != null)
                    {
                        this.m_tracer.TraceInfo("Will update {0} object from bundle...", itm);
                        data.Item[i] = svc.Update(context, itm) as IdentifiedData;
                    }
                    else
                    {
                        this.m_tracer.TraceInfo("Will insert {0} object from bundle...", itm);
                        data.Item[i] = svc.Insert(context, itm) as IdentifiedData;
                    }
                }
                catch (TargetInvocationException e)
                {
                    this.m_tracer.TraceError("Error inserting bundle: {0}", e);
                    throw e.InnerException;
                }
                catch (Exception e)
                {
                    throw new Exception($"Could not insert bundle due to sub-object persistence (bundle item {i})", e);
                }
            }

            // Cache items
            foreach (var itm in data.Item)
            {
                itm.LoadState = LoadState.FullLoad;
                context.AddCacheCommit(itm);
            }
            return(data);
        }
Example #2
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            = AdoAuditPersistenceService.GetPersister(me.GetType());

            // 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) 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) as IIdentifiedEntity;
                me.Key = inserted.Key;

                if (vMe != null)
                {
                    vMe.VersionKey = (inserted as IVersionedEntity).VersionKey;
                }
                return(inserted);
            }
            return(existing);
        }
Example #3
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  = AdoAuditPersistenceService.GetPersister(me.GetType()) as IAdoPersistenceService;
            var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>();

            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
                ApplicationServiceContext.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) as IIdentifiedEntity;
            }

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

            if (classAtt != null && existing == null)
            {
                // Get the domain type
                var dataType = AdoAuditPersistenceService.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(AdoAuditPersistenceService.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 ??
                               context.GetCacheCommit(objIdCache);
                }
                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) as IIdentifiedEntity;
                        }
                    }
                }
            }

            return(existing);
        }
Example #4
0
        /// <summary>
        /// Perform the query
        /// </summary>
        protected virtual IEnumerable <Object> QueryInternalEx(DataContext context, Expression <Func <TModel, bool> > query, Guid queryId, int offset, int?count, out int totalResults, bool incudeCount, ModelSort <TModel>[] orderBy)
        {
#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) == true)
                {
                    totalResults = (int)this.m_queryPersistence.QueryResultTotalQuantity(queryId);
                    var resultKeys = this.m_queryPersistence.GetQueryResults(queryId, offset, count.Value);
                    return(resultKeys.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, bool>(query, false);
                if (expression != null)
                {
                    Type lastJoined = typeof(TDomain);
                    if (typeof(CompositeResult).IsAssignableFrom(typeof(TQueryReturn)))
                    {
                        foreach (var p in typeof(TQueryReturn).GenericTypeArguments.Select(o => AdoAuditPersistenceService.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.TraceVerbose("Will use slow query construction due to complex mapped fields");
                    domainQuery = AdoAuditPersistenceService.GetQueryBuilder().CreateQuery(query, orderBy);
                }


                var retVal = this.DomainQueryInternal <TQueryReturn>(context, domainQuery);
                this.AppendOrderBy(retVal.Statement, orderBy);

                // Count = 0 means we're not actually fetching anything so just hit the db
                if (count != 0)
                {
                    // Stateful query identifier = We need to add query results
                    if (queryId != Guid.Empty && ApplicationServiceContext.Current.GetService <IQueryPersistenceService>() != null)
                    {
                        // Create on a separate thread the query results
                        var keys = retVal.Keys <Guid>().ToArray();
                        totalResults = keys.Length;
                        this.m_queryPersistence?.RegisterQuerySet(queryId, keys, query, totalResults);
                    }
                    else if (count.HasValue && !AdoAuditPersistenceService.GetConfiguration().UseFuzzyTotals) // Get an exact total
                    {
                        totalResults = retVal.Count();
                    }
                    else
                    {
                        totalResults = 0;
                    }

                    // Fuzzy totals - This will only fetch COUNT + 1 as the total results
                    if (count.HasValue)
                    {
                        if ((AdoAuditPersistenceService.GetConfiguration().UseFuzzyTotals) && totalResults == 0)
                        {
                            var fuzzResults = retVal.Skip(offset).Take(count.Value + 1).OfType <Object>().ToList();
                            totalResults = offset + fuzzResults.Count();
                            return(fuzzResults.Take(count.Value));
                        }
                        else
                        {
                            return(retVal.Skip(offset).Take(count.Value).OfType <Object>());
                        }
                    }
                    else
                    {
                        return(retVal.Skip(offset).OfType <Object>());
                    }
                }
                else
                {
                    totalResults = retVal.Count();
                    return(new List <Object>());
                }
            }
            catch (Exception ex)
            {
                if (domainQuery != null)
                {
                    this.m_tracer.TraceError(context.GetQueryLiteral(domainQuery.Build()));
                }
                context.Dispose(); // No longer important

                throw;
            }
#if DEBUG
            finally
            {
                sw.Stop();
            }
#endif
        }