/// <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> /// 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> /// 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>()); }