예제 #1
0
        /// <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;
                }
            }
        }
예제 #2
0
        /// <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
            }
        }