/// <summary> /// Queries for the specified model. /// </summary> /// <param name="query">The query.</param> /// <param name="offset">The offset.</param> /// <param name="count">The count.</param> /// <param name="authContext">The authentication context.</param> /// <param name="totalCount">The total count.</param> /// <param name="fastQuery">if set to <c>true</c> [fast query].</param> /// <returns>Returns a list of the specified model instance which match the given query expression.</returns> /// <exception cref="System.ArgumentNullException">query</exception> /// <exception cref="DataPersistenceException">Cannot perform LINQ query</exception> public virtual IEnumerable <TModel> QueryInternal(Expression <Func <TModel, bool> > query, int offset, int?count, IPrincipal authContext, out int totalCount, bool fastQuery) { if (query == null) { throw new ArgumentNullException(nameof(query)); } var preArgs = new PreQueryEventArgs <TModel>(query, authContext); this.Querying?.Invoke(this, preArgs); if (preArgs.Cancel) { this.traceSource.TraceEvent(TraceEventType.Warning, 0, "Pre-Event handler indicates abort query {0}", query); totalCount = 0; return(null); } // Query object using (var connection = Configuration.Provider.GetReadonlyConnection()) { try { connection.Open(); this.traceSource.TraceEvent(TraceEventType.Verbose, 0, "QUERY {0}", query); if ((count ?? 1000) > 25) { connection.PrepareStatements = true; } if (fastQuery) { connection.AddData("loadFast", true); } var results = this.Query(connection, query, offset, count ?? 1000, out totalCount, true, authContext); var postData = new PostQueryEventArgs <TModel>(query, results.AsQueryable(), authContext); this.Queried?.Invoke(this, postData); var retVal = postData.Results.AsParallel().ToList(); this.traceSource.TraceEvent(TraceEventType.Verbose, 0, $"Returning {offset}..{offset + (count ?? 1000)} or {totalCount} results"); return(retVal); } catch (Exception e) { this.traceSource.TraceEvent(TraceEventType.Error, 0, $"Error: {e}"); throw; } } }
/// <summary> /// Instructs the service /// </summary> protected virtual IEnumerable <TData> QueryInternal(Expression <Func <TData, bool> > query, Guid queryId, int offset, int?count, IPrincipal authContext, out int totalCount, bool fastQuery) { if (query == null) { throw new ArgumentNullException(nameof(query)); } #if DEBUG Stopwatch sw = new Stopwatch(); sw.Start(); #endif PreQueryEventArgs <TData> preArgs = new PreQueryEventArgs <TData>(query, authContext); this.Querying?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceEvent(TraceEventType.Warning, 0, "Pre-Event handler indicates abort query {0}", query); totalCount = 0; return(null); } // Query object using (var connection = m_configuration.Provider.GetReadonlyConnection()) try { this.ThrowIfExceeded(); connection.Open(); this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "QUERY {0}", query); // Is there an obsoletion item already specified? if ((count ?? 1000) > 25) { connection.PrepareStatements = true; } if (fastQuery) { connection.AddData("loadFast", true); connection.LoadState = LoadState.PartialLoad; } else { connection.LoadState = LoadState.FullLoad; } var results = this.Query(connection, query, queryId, offset, count ?? 1000, out totalCount, true, authContext); var postData = new PostQueryEventArgs <TData>(query, results.AsQueryable(), authContext); this.Queried?.Invoke(this, postData); var retVal = postData.Results.ToList(); // Add to cache foreach (var i in retVal.AsParallel().Where(i => i != null)) { connection.AddCacheCommit(i); } ApplicationContext.Current.GetService <IThreadPoolService>()?.QueueUserWorkItem(o => { foreach (var itm in (o as IEnumerable <IdentifiedData>)) { ApplicationContext.Current.GetService <IDataCachingService>()?.Add(itm); } }, connection.CacheOnCommit.ToList()); this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Returning {0}..{1} or {2} results", offset, offset + (count ?? 1000), totalCount); return(retVal); } catch (NotSupportedException e) { throw new DataPersistenceException("Cannot perform LINQ query", e); } catch (Exception e) { this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e); throw; } finally { #if DEBUG sw.Stop(); this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Query {0} took {1} ms", query, sw.ElapsedMilliseconds); #endif Interlocked.Decrement(ref m_currentRequests); } }
/// <summary> /// Instructs the service /// </summary> protected virtual IEnumerable <TData> QueryInternal(Expression <Func <TData, bool> > query, int offset, int?count, IPrincipal authContext, out int totalCount, bool fastQuery) { if (query == null) { throw new ArgumentNullException(nameof(query)); } #if DEBUG Stopwatch sw = new Stopwatch(); sw.Start(); #endif PreQueryEventArgs <TData> preArgs = new PreQueryEventArgs <TData>(query, authContext); this.Querying?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceEvent(TraceEventType.Warning, 0, "Pre-Event handler indicates abort query {0}", query); totalCount = 0; return(null); } // Query object using (var connection = new ModelDataContext(m_configuration.ReadonlyConnectionString)) try { connection.LoadOptions = this.GetDataLoadOptions(); this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "QUERY {0}", query); // Tracer if (m_configuration.TraceSql) { connection.Log = new LinqTraceWriter(); } var results = this.Query(connection, query, authContext); var postData = new PostQueryEventArgs <TData>(query, results, authContext); this.Queried?.Invoke(this, postData); if (count == 1 && offset == 0) { var result = postData.Results.Take(1).ToList(); totalCount = result.Count; this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Returning {0}..{1} or {2} results", offset, offset + (count ?? 1000), totalCount); return(result); } else { if (!fastQuery) { totalCount = postData.Results.Count(); } else { totalCount = -1; } // Skip postData.Results = postData.Results.Skip(offset); if (count.HasValue) { postData.Results = postData.Results.Take(count.Value); } var retVal = postData.Results.AsParallel().ToList(); this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Returning {0}..{1} or {2} results", offset, offset + (count ?? 1000), totalCount); return(retVal); } } catch (NotSupportedException e) { this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Cannot perform LINQ query, switching to stored query sqp_{0}", typeof(TData).Name); throw new DataPersistenceException("Cannot perform LINQ query", e); } catch (Exception e) { this.m_tracer.TraceEvent(TraceEventType.Error, 0, "Error : {0}", e); throw; } finally { #if DEBUG sw.Stop(); this.m_tracer.TraceEvent(TraceEventType.Verbose, 0, "Query {0} took {1} ms", query, sw.ElapsedMilliseconds); #endif } }