/// <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, PolicyIdentifiers.QueryClinicalData).Demand();
            };

            // Demand insert
            persister.Inserting += (o, e) =>
            {
                new PolicyPermission(System.Security.Permissions.PermissionState.Unrestricted, PolicyIdentifiers.WriteClinicalData).Demand();
            };

            // Demand update
            persister.Updating += (o, e) =>
            {
                new PolicyPermission(System.Security.Permissions.PermissionState.Unrestricted, PolicyIdentifiers.WriteClinicalData).Demand();
            };

            // Obsoletion permission demand
            persister.Obsoleting += (o, e) =>
            {
                new PolicyPermission(System.Security.Permissions.PermissionState.Unrestricted, PolicyIdentifiers.DeleteClinicalData).Demand();
            };

            // Queried data filter
            persister.Queried += (o, e) =>
            {
                new PolicyPermission(System.Security.Permissions.PermissionState.Unrestricted, PolicyIdentifiers.ReadClinicalData).Demand();
                DataQueryResultEventArgs <TData> dqre = e as DataQueryResultEventArgs <TData>;
                // Filter dataset
                if (dqre != null)
                {
                    dqre.Results = dqre.Results.Where(i => ApplicationContext.Current.PolicyDecisionService.GetPolicyDecision(AuthenticationContext.Current.Principal, i) == OpenIZ.Core.Model.Security.PolicyGrantType.Grant);
                }
            };
        }
        /// <summary>
        /// Query function returning results and count control
        /// </summary>
        private IEnumerable <TData> Query(System.Linq.Expressions.Expression <Func <TData, bool> > query, int offset, int?count, out int totalResults, Guid queryId, bool countResults, bool fastQuery, IEnumerable <String> expandProperties = null)
        {
            if (query == null)
            {
                throw new ArgumentNullException(nameof(query));
            }

            DataQueryPreEventArgs <TData> preArgs = new DataQueryPreEventArgs <TData>(query, offset, count);

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

                        if (expandProperties != null)
                        {
                            context.LoadAssociations = expandProperties.ToArray();
                        }

                        results = this.Query(context, query, offset, count ?? -1, out totalResults, queryId, countResults);
                    }

                    var postData = new DataQueryResultEventArgs <TData>(query, results, offset, count, totalResults);
                    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 (NotSupportedException e)
                {
                    this.m_tracer.TraceVerbose("Cannot perform LINQ query, switching to stored query sqp_{0}", typeof(TData).Name, e);

                    // Build dictionary
                    var httpValues = QueryExpressionBuilder.BuildQuery <TData>(query, true);
                    var filter     = new Dictionary <String, Object>();

                    foreach (var f in httpValues)
                    {
                        object existing = null;
                        if (filter.TryGetValue(f.Key, out existing))
                        {
                            if (!(existing is IList))
                            {
                                existing = new List <Object>()
                                {
                                    existing
                                };
                                filter[f.Key] = existing;
                            }
                            (existing as IList).Add(f.Value);
                        }
                        else
                        {
                            filter.Add(f.Key, f.Value);
                        }
                    }
                    // Query
                    return(this.Query(String.Format("sqp_{0}", typeof(TData).Name), filter, offset, count, out totalResults, queryId));
                }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error : {0}", e);
                throw;
            }
#if PERFMON
            finally
            {
                sw.Stop();
                ApplicationContext.Current.PerformanceLog(typeof(TData).Name, nameof(Query), query.ToString(), sw.Elapsed);
            }
#endif
        }