private void Query_ResultReady(object sender, QueryResultEventArgs args) { this.ClearGraphics(2); // Toggle to Results Panel if (args.Results != null && args.Results.Features.Count > 0) { isFirstLoad = true; // Suppress filter results by map extent or pan map QueryResultMessage.Visibility = Visibility.Collapsed; FeatureSet fset = args.Results; Symbol symbol = ChooseSymbol(fset.GeometryType.ToString(), false); GeoFeatureCollection dataset = new GeoFeatureCollection(args.QueryLayer.OutputFields, args.QueryLayer.OutputLabels, fset.DisplayFieldName, args.QueryLayer.Title); foreach (Graphic feature in fset.Features) { feature.Symbol = symbol; feature.Geometry.SpatialReference = fset.SpatialReference; this.GraphicsLayer.Graphics.Add(feature); dataset.Add(feature); } this.FeatureSets.Add(dataset); this.GraphicsTipTemplate = args.QueryLayer.MapTipTemplate; this.MapControl.ZoomTo(GeometryTool.ExpandGeometryExtent(this.GraphicsLayer.FullExtent, 0.25)); } else { QueryResultMessage.Visibility = Visibility.Visible; QueryResultMessage.Text = string.Format("Sorry! {0}", (string.IsNullOrEmpty(args.ErrorMsg)) ? "No features are found." : args.ErrorMsg); } this.IsBusy = false; }
/// <summary> /// Find with stored query parameters /// </summary> public virtual IEnumerable <TEntity> Find(Expression <Func <TEntity, bool> > query, int offset, int?count, out int totalResults, Guid queryId, params ModelSort <TEntity>[] orderBy) { // Demand permission this.DemandQuery(); // Call privacy hook if (this.m_privacyService?.ValidateQuery(query, AuthenticationContext.Current.Principal) == false) { this.ThrowPrivacyValidationException(query); } var persistenceService = ApplicationServiceContext.Current.GetService <IDataPersistenceService <TEntity> >(); if (persistenceService == null) { throw new InvalidOperationException(this.m_localizationService.FormatString("error.server.core.servicePersistence", new { param = typeof(IDataPersistenceService <TEntity>).FullName })); } var businessRulesService = ApplicationServiceContext.Current.GetBusinessRulesService <TEntity>(); // Notify query var preQueryEventArgs = new QueryRequestEventArgs <TEntity>(query, offset, count, queryId, AuthenticationContext.Current.Principal, orderBy); this.Querying?.Invoke(this, preQueryEventArgs); IEnumerable <TEntity> results = null; if (preQueryEventArgs.Cancel) /// Cancel the request { totalResults = preQueryEventArgs.TotalResults; results = preQueryEventArgs.Results; } else { if (queryId != Guid.Empty && persistenceService is IStoredQueryDataPersistenceService <TEntity> ) { results = (persistenceService as IStoredQueryDataPersistenceService <TEntity>).Query(preQueryEventArgs.Query, preQueryEventArgs.QueryId.GetValueOrDefault(), preQueryEventArgs.Offset, preQueryEventArgs.Count, out totalResults, AuthenticationContext.Current.Principal, orderBy); } else { results = persistenceService.Query(preQueryEventArgs.Query, preQueryEventArgs.Offset, preQueryEventArgs.Count, out totalResults, AuthenticationContext.Current.Principal, orderBy); } } // 1. Let the BRE run var retVal = businessRulesService != null?businessRulesService.AfterQuery(results) : results; // 2. Broadcast query performed var postEvt = new QueryResultEventArgs <TEntity>(query, retVal, offset, count, totalResults, queryId, AuthenticationContext.AnonymousPrincipal); this.Queried?.Invoke(this, postEvt); totalResults = postEvt.TotalResults; // 2. Apply Filters if needed retVal = this.m_privacyService?.Apply(retVal, AuthenticationContext.Current.Principal) ?? retVal; return(retVal); }
/// <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, out int totalCount, bool fastQuery, IPrincipal overrideAuthContext) { if (query == null) { throw new ArgumentNullException(nameof(query)); } var preArgs = new QueryRequestEventArgs <TModel>(query, offset, count, null, overrideAuthContext); this.Querying?.Invoke(this, preArgs); if (preArgs.Cancel) { this.traceSource.TraceEvent(EventLevel.Warning, "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(EventLevel.Verbose, "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); var postData = new QueryResultEventArgs <TModel>(query, results.AsQueryable(), offset, count, totalCount, null, overrideAuthContext); this.Queried?.Invoke(this, postData); var retVal = postData.Results.AsParallel().WithDegreeOfParallelism(2).ToList(); this.traceSource.TraceEvent(EventLevel.Verbose, $"Returning {offset}..{offset + (count ?? 1000)} or {totalCount} results"); return(retVal); } catch (Exception e) { this.traceSource.TraceEvent(EventLevel.Error, $"Error: {e}"); throw; } } }
/// <summary> /// Find with stored query parameters /// </summary> public virtual IEnumerable <TEntity> Find(Expression <Func <TEntity, bool> > query, int offset, int?count, out int totalResults, Guid queryId, params ModelSort <TEntity>[] orderBy) { // Demand permission this.DemandQuery(); var persistenceService = ApplicationContext.Current.GetService <IDataPersistenceService <TEntity> >(); if (persistenceService == null) { throw new InvalidOperationException($"Unable to locate {typeof(IDataPersistenceService<TEntity>).FullName}"); } // Fire pre event var preEvtArgs = new QueryRequestEventArgs <TEntity>(query, offset, count, queryId, AuthenticationContext.Current.Principal, orderBy); this.Querying?.Invoke(this, preEvtArgs); if (preEvtArgs.Cancel) { this.m_traceSource.TraceWarning("Pre-query event indicates cancel"); totalResults = preEvtArgs.TotalResults; return(preEvtArgs.Results); } var businessRulesService = ApplicationContext.Current.GetService <IBusinessRulesService <TEntity> >(); IEnumerable <TEntity> results = null; if (persistenceService is IStoredQueryDataPersistenceService <TEntity> ) { results = (persistenceService as IStoredQueryDataPersistenceService <TEntity>).Query(query, queryId, offset, count, out totalResults, AuthenticationContext.Current.Principal, orderBy); } else { results = persistenceService.Query(query, offset, count, out totalResults, AuthenticationContext.Current.Principal, orderBy); } var retVal = businessRulesService != null?businessRulesService.AfterQuery(results) : results; var postEvt = new QueryResultEventArgs <TEntity>(query, retVal, offset, count, totalResults, queryId, AuthenticationContext.AnonymousPrincipal); this.Queried?.Invoke(this, postEvt); totalResults = postEvt.TotalResults; return(postEvt.Results); }
/// <summary> /// Bind the enforcement point /// </summary> protected void BindClinicalEnforcement <TData>(IDataPersistenceService <TData> persister) where TData : IdentifiedData { // Demand query persister.Querying += (o, e) => { new PolicyPermission(System.Security.Permissions.PermissionState.Unrestricted, PermissionPolicyIdentifiers.QueryClinicalData).Demand(); }; // Demand insert persister.Inserting += (o, e) => { new PolicyPermission(System.Security.Permissions.PermissionState.Unrestricted, PermissionPolicyIdentifiers.WriteClinicalData).Demand(); }; // Demand update persister.Updating += (o, e) => { new PolicyPermission(System.Security.Permissions.PermissionState.Unrestricted, PermissionPolicyIdentifiers.WriteClinicalData).Demand(); }; // Obsoletion permission demand persister.Obsoleting += (o, e) => { new PolicyPermission(System.Security.Permissions.PermissionState.Unrestricted, PermissionPolicyIdentifiers.DeleteClinicalData).Demand(); }; // Queried data filter persister.Queried += (o, e) => { new PolicyPermission(System.Security.Permissions.PermissionState.Unrestricted, PermissionPolicyIdentifiers.ReadClinicalData).Demand(); QueryResultEventArgs <TData> dqre = e as QueryResultEventArgs <TData>; // Filter dataset if (dqre != null) { dqre.Results = dqre.Results.Where(i => ApplicationContext.Current.PolicyDecisionService.GetPolicyDecision(AuthenticationContext.Current.Principal, i).Outcome == SanteDB.Core.Model.Security.PolicyGrantType.Grant); } }; }
private void Query_ResultReady(object sender, QueryResultEventArgs args) { this.ClearGraphics(1); // Toggle to Results Panel this.FeatureSets.Clear(); if (args.Results != null && args.Results.Features.Count > 0) { ChartResultMessage.Visibility = Visibility.Collapsed; FeatureSet fset = args.Results; this.GraphicsTipTemplate = args.QueryLayer.MapTipTemplate; CreateSeriesChart(fset, args.QueryLayer as ChartQueryLayer); this.FeatureSets.Add(new GeoFeatureCollection(fset, args.QueryLayer.Title)); BindDataToGrid(fset); } else { ChartResultMessage.Visibility = Visibility.Visible; ChartResultMessage.Text = string.Format("Sorry! {0}", (string.IsNullOrEmpty(args.ErrorMsg)) ? "No features are found." : args.ErrorMsg); } this.IsBusy = false; }
/// <summary> /// Execute the current operation /// </summary> public IEnumerable <object> Execute(SubscriptionDefinition subscription, NameValueCollection parameters, int offset, int?count, out int totalResults, Guid queryId) { if (subscription == null || subscription.ServerDefinitions.Count == 0) { throw new InvalidOperationException("Subscription does not have server definition"); } try { var preArgs = new QueryRequestEventArgs <IdentifiedData>(o => o.Key == subscription.Key, offset, count, queryId, AuthenticationContext.Current.Principal, new ModelSort <IdentifiedData> [0], parameters); this.Executing?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event for executor failed"); totalResults = preArgs.TotalResults; return(preArgs.Results); } var persistenceType = typeof(IDataPersistenceService <>).MakeGenericType(subscription.ResourceType); var persistenceInstance = ApplicationServiceContext.Current.GetService(persistenceType) as IAdoPersistenceService; var queryService = ApplicationServiceContext.Current.GetService <IQueryPersistenceService>(); var cacheService = ApplicationServiceContext.Current.GetService <IDataCachingService>(); // Get the definition var definition = subscription.ServerDefinitions.FirstOrDefault(o => o.InvariantName == m_configuration.Provider.Invariant); if (definition == null) { throw new InvalidOperationException($"Subscription does not provide definition for provider {m_configuration.Provider.Invariant}"); } // No obsoletion time? if (typeof(IBaseEntityData).IsAssignableFrom(subscription.ResourceType) && !parameters.ContainsKey("obsoletionTime")) { parameters.Add("obsoletionTime", "null"); } // Query expression var queryExpression = typeof(QueryExpressionParser).GetGenericMethod( nameof(QueryExpressionParser.BuildLinqExpression), new Type[] { subscription.ResourceType }, new Type[] { typeof(NameValueCollection) } ).Invoke(null, new object[] { parameters }); // Query has been registered? IEnumerable <IdentifiedData> result = null; if (queryId != Guid.Empty && queryService?.IsRegistered(queryId) == true) { totalResults = (int)queryService.QueryResultTotalQuantity(queryId); result = queryService.GetQueryResults(queryId, offset, count ?? 100) .Select(o => { try { var retVal = cacheService.GetCacheItem(o); if (retVal == null) { using (var ctx = m_configuration.Provider.GetReadonlyConnection()) { ctx.Open(); ctx.LoadState = LoadState.FullLoad; retVal = persistenceInstance.Get(ctx, o) as IdentifiedData; cacheService?.Add(retVal); } } return(retVal); } catch (Exception e) { this.m_tracer.TraceError("Error fetching query results for {0}: {1}", queryId, e); throw new DataPersistenceException("Error fetching query results", e); } }).OfType <IdentifiedData>().ToList(); } else { // Now grab the context and query!!! using (var connection = m_configuration.Provider.GetReadonlyConnection()) { try { connection.Open(); connection.LoadState = LoadState.FullLoad; // First, build the query using the query build TableMapping tableMapping = null; if (typeof(Entity).IsAssignableFrom(subscription.ResourceType)) { tableMapping = TableMapping.Get(typeof(DbEntityVersion)); } else if (typeof(Act).IsAssignableFrom(subscription.ResourceType)) { tableMapping = TableMapping.Get(typeof(DbActVersion)); } else if (typeof(Concept).IsAssignableFrom(subscription.ResourceType)) { tableMapping = TableMapping.Get(typeof(DbConceptVersion)); } else { throw new InvalidOperationException("ADO Subscriptions only support Entities and Acts (or sub-types)"); } var query = (typeof(QueryBuilder).GetGenericMethod( nameof(QueryBuilder.CreateQuery), new Type[] { subscription.ResourceType }, new Type[] { queryExpression.GetType(), typeof(ColumnMapping).MakeArrayType() } ).Invoke(this.m_queryBuilder, new object[] { queryExpression, tableMapping.Columns.ToArray() }) as SqlStatement).Build(); // Now we want to remove the portions of the built query statement after FROM and before WHERE as the definition will be the source of our selection SqlStatement domainQuery = new SqlStatement(m_configuration.Provider, query.SQL.Substring(0, query.SQL.IndexOf(" FROM "))); // Append our query var definitionQuery = definition.Definition; List <Object> values = new List <object>(); definitionQuery = this.m_parmRegex.Replace(definitionQuery, (o) => { if (parameters.TryGetValue("_" + o.Groups[2].Value.Substring(1, o.Groups[2].Value.Length - 2), out List <String> qValue)) { Guid uuid = Guid.Empty; if (Guid.TryParse(qValue.First(), out uuid)) { values.AddRange(qValue.Select(v => Guid.Parse(v)).OfType <Object>()); } else { values.AddRange(qValue); } return(o.Groups[1].Value + String.Join(",", qValue.Select(v => "?"))); } return("NULL"); }); // Now we want to append domainQuery.Append(" FROM (").Append(definitionQuery, values.ToArray()).Append($") AS {tableMapping.TableName} "); domainQuery.Append(query.SQL.Substring(query.SQL.IndexOf("WHERE ")), query.Arguments.ToArray()); // Now we want to create the result type var resultType = tableMapping.OrmType; if (typeof(IDbVersionedData).IsAssignableFrom(resultType)) // type is versioned so we have to join { var fkType = tableMapping.GetColumn("Key").ForeignKey.Table; resultType = typeof(CompositeResult <,>).MakeGenericType(resultType, fkType); } // Now we want to select out our results if (count == 0) { totalResults = connection.Count(domainQuery); return(null); } else { // Fetch var domainResults = typeof(DataContext).GetGenericMethod( nameof(DataContext.Query), new Type[] { resultType }, new Type[] { typeof(SqlStatement) }).Invoke(connection, new object[] { domainQuery }) as IOrmResultSet; IEnumerable <object> resultObjects = null; // Register query if query id specified if (queryId != Guid.Empty) { var results = domainResults.Keys <Guid>().OfType <Guid>().ToArray(); this.m_tracer.TraceVerbose("Query for Keys: {0}", connection.GetQueryLiteral(domainResults.Keys <Guid>().ToSqlStatement())); totalResults = results.Count(); ApplicationServiceContext.Current.GetService <IQueryPersistenceService>()?.RegisterQuerySet(queryId, results, null, totalResults); resultObjects = results.Skip(offset).Take(count ?? 100).OfType <Object>(); } else if (m_configuration.UseFuzzyTotals || preArgs.UseFuzzyTotals) { this.m_tracer.TraceVerbose("Query for Objects: {0}", connection.GetQueryLiteral(domainResults.ToSqlStatement())); resultObjects = domainResults.Skip(offset).Take((count ?? 100) + 1).OfType <Object>(); totalResults = domainResults.Count(); } else { this.m_tracer.TraceVerbose("Query for Objects: {0}", connection.GetQueryLiteral(domainResults.ToSqlStatement())); totalResults = domainResults.Count(); resultObjects = domainResults.Skip(offset).Take(count ?? 100).OfType <Object>(); } this.m_tracer.TraceVerbose("If i show up in the log, the log is ???????? WHY?????"); // Return result = resultObjects .Take(count ?? 100) .OfType <Object>() .Select(o => { try { if (o is Guid) { var retVal = cacheService.GetCacheItem((Guid)o); if (retVal == null) { using (var subConn = connection.OpenClonedContext()) { retVal = persistenceInstance.Get(subConn, (Guid)o) as IdentifiedData; cacheService?.Add(retVal); } } return(retVal); } else { var idData = (o as CompositeResult)?.Values.OfType <IDbIdentified>().FirstOrDefault() ?? o as IDbIdentified; var retVal = cacheService.GetCacheItem(idData.Key); if (retVal == null) { using (var subConn = connection.OpenClonedContext()) { retVal = persistenceInstance.ToModelInstance(o, subConn) as IdentifiedData; cacheService?.Add(retVal); } } return(retVal); } } catch (Exception e) { this.m_tracer.TraceError("Error converting result: {0}", e); throw; } }).OfType <IdentifiedData>().ToList(); } } catch (Exception e) { #if DEBUG this.m_tracer.TraceError("Error executing subscription: {0}", e); #else this.m_tracer.TraceError("Error executing subscription: {0}", e.Message); #endif throw new DataPersistenceException($"Error executing subscription: {e.Message}", e); } } // using conn } // if var postEvt = new QueryResultEventArgs <IdentifiedData>(o => o.Key == subscription.Key, result, offset, count, totalResults, queryId, AuthenticationContext.Current.Principal); this.Executed?.Invoke(this, postEvt); // Now set the overridden data return(postEvt.Results); } catch (Exception e) { this.m_tracer.TraceError("Error executing core ADO Subscription logic for {0}: {1}", subscription.Key, e); throw new Exception($"Error executing core ADO subscription logic for {subscription.Key}", e); } }
/// <summary> /// Query function returning results and count control /// </summary> private IEnumerable <TData> Query(System.Linq.Expressions.Expression <Func <TData, bool> > query, Guid?queryId, int offset, int?count, out int totalResults, bool countResults, bool fastQuery, IPrincipal principal, ModelSort <TData>[] orderBy) { if (query == null) { throw new ArgumentNullException(nameof(query)); } QueryRequestEventArgs <TData> preArgs = new QueryRequestEventArgs <TData>(query, offset, count, queryId, principal, orderBy); this.Querying?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event handler indicates abort query {0}", query); totalResults = preArgs.TotalResults; return(preArgs.Results); } #if PERFMON Stopwatch sw = new Stopwatch(); sw.Start(); #endif // Query object using (var context = this.CreateReadonlyConnection(principal)) try { IEnumerable <TData> results = null; using (context.LockConnection()) { this.m_tracer.TraceVerbose("QUERY {0}", query); if (fastQuery) { context.DelayLoadMode = LoadState.PartialLoad; } else { context.DelayLoadMode = LoadState.FullLoad; } results = this.Query(context, query, queryId.GetValueOrDefault(), offset, count ?? -1, out totalResults, countResults, orderBy); } var postData = new QueryResultEventArgs <TData>(query, results, offset, count, totalResults, queryId, principal); this.Queried?.Invoke(this, postData); totalResults = postData.TotalResults; // Remove from the cache foreach (var itm in context.CacheOnCommit.AsParallel()) { ApplicationContext.Current.GetService <IDataCachingService>()?.Add(itm); } return(postData.Results); } catch (SQLiteException e) { this.m_tracer.TraceError("Error executing query {1} : {0}", e, context.Connection); throw new DataPersistenceException($"Data error executing query againt {typeof(TData)}", e); } catch (Exception e) { this.m_tracer.TraceError("Error : {0}", e); throw new DataPersistenceException($"Error executing query against {typeof(TData)}", e); } #if PERFMON finally { sw.Stop(); ApplicationContext.Current.PerformanceLog(typeof(TData).Name, nameof(Query), query.ToString(), sw.Elapsed); } #endif }
/// <summary> /// Instructs the service /// </summary> protected virtual IEnumerable <TData> QueryInternal(Expression <Func <TData, bool> > query, Guid queryId, int offset, int?count, out int totalCount, bool fastQuery, IPrincipal overrideAuthContext, ModelSort <TData>[] orderBy, Expression <Func <TData, bool> >[] unionWith) { if (query == null) { throw new ArgumentNullException(nameof(query)); } else if (count.GetValueOrDefault() > (this.m_settingsProvider.GetConfiguration().MaxPageSize ?? 2500)) { throw new ArgumentOutOfRangeException($"Server does not permit more than {this.m_settingsProvider.GetConfiguration().MaxPageSize ?? 2500} results in a single fetch"); } #if DEBUG Stopwatch sw = new Stopwatch(); sw.Start(); #endif QueryRequestEventArgs <TData> preArgs = new QueryRequestEventArgs <TData>(query, offset, count, queryId, overrideAuthContext, orderBy); this.Querying?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceEvent(EventLevel.Warning, "Pre-Event handler indicates abort query {0}", query); totalCount = preArgs.TotalResults; return(preArgs.Results); } // Query object using (var connection = this.m_settingsProvider.GetConfiguration().Provider.GetReadonlyConnection()) try { connection.Open(); this.m_tracer.TraceEvent(EventLevel.Verbose, "QUERY {0}", query); // Is there an obsoletion item already specified? if (fastQuery) { connection.AddData("loadFast", true); connection.LoadState = LoadState.PartialLoad; } else { connection.LoadState = LoadState.FullLoad; } connection.AddData("principal", overrideAuthContext); // Other results we want to intersect with? if (unionWith != null) { connection.AddData("UNION", unionWith); } var results = this.Query(connection, preArgs.Query, queryId, preArgs.Offset, preArgs.Count ?? 25, out totalCount, orderBy, true).ToList(); var postData = new QueryResultEventArgs <TData>(query, results.AsQueryable(), offset, count, totalCount, queryId, overrideAuthContext); this.Queried?.Invoke(this, postData); var retVal = postData.Results; // Add to cache foreach (var i in retVal.Where(i => i != null)) { ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(i); } this.m_tracer.TraceEvent(EventLevel.Verbose, "Returning {0}..{1} or {2} results", offset, offset + (count ?? 1000), totalCount); return(retVal); } catch (NotSupportedException e) { throw new DataPersistenceException("Cannot perform LINQ query as underlying persistence provider does not support it", e); } catch (Exception e) { this.m_tracer.TraceEvent(EventLevel.Error, "Error : {0}", e); throw new DataPersistenceException($"Error performing query {query}", e); } finally { #if DEBUG sw.Stop(); this.m_tracer.TraceEvent(EventLevel.Verbose, "Query {0} took {1} ms", query, sw.ElapsedMilliseconds); #endif } }
/// <summary> /// Cannot query bundles /// </summary> protected override void OnQueried(object sender, QueryResultEventArgs <Bundle> e) { throw new NotSupportedException("Cannot query bundles"); }
/// <summary> /// Executes a query for the specified objects /// </summary> public IEnumerable <AuditData> Query(Expression <Func <AuditData, bool> > query, int offset, int?count, out int totalCount, IPrincipal overrideAuthContext = null, params ModelSort <AuditData>[] orderBy) { var preEvtData = new QueryRequestEventArgs <AuditData>(query, offset: offset, count: count, queryId: null, principal: overrideAuthContext); this.Querying?.Invoke(this, preEvtData); if (preEvtData.Cancel) { this.m_traceSource.TraceWarning("Pre-event handler for query indicates cancel : {0}", query); totalCount = 0; return(null); } try { using (var context = this.m_configuration.Provider.GetReadonlyConnection()) { context.Open(); var sql = this.m_builder.CreateQuery(query).Build(); if (orderBy != null && orderBy.Length > 0) { foreach (var ob in orderBy) { sql = sql.OrderBy <DbAuditData>(this.m_mapper.MapModelExpression <AuditData, DbAuditData, dynamic>(ob.SortProperty), ob.SortOrder); } } else { sql = sql.OrderBy <DbAuditData>(o => o.Timestamp, SortOrderType.OrderByDescending); } // Total results totalCount = context.Count(sql); // Query control if (count.GetValueOrDefault() == 0) { sql.Offset(offset).Limit(100); } else { sql.Offset(offset).Limit(count.Value); } sql = sql.Build(); var itm = context.Query <CompositeResult <DbAuditData, DbAuditCode> >(sql).ToList(); AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.Success, sql.ToString(), itm.Select(o => o.Object1.Key).ToArray()); var results = itm.Select(o => this.ToModelInstance(context, o)).ToList().AsQueryable(); // Event args var postEvtArgs = new QueryResultEventArgs <AuditData>(query, results, offset, count, totalCount, null, overrideAuthContext); this.Queried?.Invoke(this, postEvtArgs); return(postEvtArgs.Results); } } catch (Exception e) { AuditUtil.AuditAuditLogUsed(ActionType.Read, OutcomeIndicator.EpicFail, query.ToString()); this.m_traceSource.TraceError("Could not query audit {0}: {1}", query, e); throw; } }
/// <summary> /// Performs query logic /// </summary> /// <param name="query">The query</param> /// <param name="queryId">The query identifier</param> /// <param name="offset">The offset of the query</param> /// <param name="count">The total count to return</param> /// <param name="authContext">The authentication context</param> /// <param name="totalCount">The total results matching</param> /// <param name="fastQuery">True if fast querying should be performed</param> /// <returns>The matching results</returns> protected virtual IEnumerable <TModel> QueryInvoke(Expression <Func <TModel, bool> > query, Guid queryId, int offset, int?count, IPrincipal authContext, out int totalCount, bool fastQuery, ModelSort <TModel>[] orderBy) { if (query == null) { throw new ArgumentNullException(nameof(query)); } #if DEBUG Stopwatch sw = new Stopwatch(); sw.Start(); #endif QueryRequestEventArgs <TModel> preArgs = new QueryRequestEventArgs <TModel>(query, offset, count, queryId, authContext, orderBy); this.Querying?.Invoke(this, preArgs); if (preArgs.Cancel) { this.m_tracer.TraceWarning("Pre-Event handler indicates abort query {0}", query); totalCount = preArgs.TotalResults; return(preArgs.Results); } // Query object using (var connection = AdoAuditPersistenceService.GetConfiguration().Provider.GetReadonlyConnection()) try { connection.Open(); this.m_tracer.TraceVerbose("QUERY {0}", query); // Is there an obsoletion item already specified? if (fastQuery) { connection.AddData("loadFast", true); connection.LoadState = LoadState.PartialLoad; } else { connection.LoadState = LoadState.FullLoad; } var results = this.QueryInternal(connection, query, queryId, offset, count ?? 1000, out totalCount, authContext, true, orderBy); var postData = new QueryResultEventArgs <TModel>(query, results.AsQueryable(), offset, count, totalCount, queryId, 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); } ApplicationServiceContext.Current.GetService <IThreadPoolService>()?.QueueUserWorkItem(o => { foreach (var itm in (o as IEnumerable <IdentifiedData>)) { ApplicationServiceContext.Current.GetService <IDataCachingService>()?.Add(itm); } }, connection.CacheOnCommit.ToList()); this.m_tracer.TraceVerbose("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.TraceError("Error : {0}", e); throw; } finally { #if DEBUG sw.Stop(); this.m_tracer.TraceVerbose("Query {0} took {1} ms", query, sw.ElapsedMilliseconds); #endif } }