Пример #1
0
        /// <summary>
        /// Gets or executes teh result context
        /// </summary>
        public BisResultContext GetOrExecuteQuery(string name)
        {
            BisResultContext retVal = null;

            if (!this.m_dataSources.TryGetValue(name, out retVal))
            {
                var viewDef = this.m_report.DataSource.FirstOrDefault(o => o.Name == name);
                if (viewDef == null)
                {
                    throw new KeyNotFoundException($"Datasource {name} not found");
                }

                viewDef = BiUtils.ResolveRefs(viewDef);

                // Get the datasource for the execution engine
                var dsource = (viewDef as BiViewDefinition)?.Query?.DataSources.FirstOrDefault(o => o.Name == "main") ?? (viewDef as BiViewDefinition)?.Query?.DataSources.FirstOrDefault() ??
                              (viewDef as BiQueryDefinition)?.DataSources.FirstOrDefault(o => o.Name == "main") ?? (viewDef as BiQueryDefinition)?.DataSources.FirstOrDefault();

                IBiDataSource providerImplementation = null;
                if (dsource.ProviderType != null)
                {
                    providerImplementation = ApplicationServiceContext.Current.GetService <IServiceManager>().CreateInjected(dsource.ProviderType) as IBiDataSource;
                }
                else
                {
                    providerImplementation = ApplicationServiceContext.Current.GetService <IBiDataSource>(); // Global default
                }
                // Load from cache instead of DB?
                var cacheService = ApplicationServiceContext.Current.GetService <IAdhocCacheService>();
                var key          = $"{name}?{String.Join("&", this.Parameters.Select(o => $"{o.Key}={o.Value}"))}";
                var cacheResult  = cacheService?.Get <IEnumerable <dynamic> >(key);

                int count = 10000;
                if (this.m_maxResultSetSize.HasValue)
                {
                    count = this.m_maxResultSetSize.Value;
                }
                else if (this.Parameters.TryGetValue("_count", out var parameterCount) && Int32.TryParse(parameterCount.ToString(), out var tCount))
                {
                    count = tCount;
                }

                if (cacheResult != null)
                {
                    return(new BisResultContext(null, this.Parameters, providerImplementation, cacheResult, DateTime.Now));
                }
                else if (viewDef is BiViewDefinition)
                {
                    retVal = providerImplementation.ExecuteView(viewDef as BiViewDefinition, this.Parameters, 0, count);
                }
                else if (viewDef is BiQueryDefinition)
                {
                    retVal = providerImplementation.ExecuteQuery(viewDef as BiQueryDefinition, this.Parameters, null, 0, count);
                }
                else
                {
                    throw new InvalidOperationException($"Cannot determine data source type of {name}");
                }

                cacheService?.Add(key, retVal.Dataset, new TimeSpan(0, 1, 0));
                this.m_dataSources.Add(name, retVal);
            }
            return(retVal);
        }
Пример #2
0
        /// <summary>
        /// Pivot provider
        /// </summary>
        public BisResultContext Pivot(BisResultContext context, BiViewPivotDefinition pivot)
        {
            var buckets = new List <ExpandoObject>();

            // First we must order by the pivot
            context.Dataset.OrderBy(o => (o as IDictionary <String, Object>)[pivot.Key]);

            // Algorithm for pivoting :
            IDictionary <String, Object> cobject = null;

            foreach (IDictionary <String, Object> itm in context.Dataset)
            {
                var key = itm[pivot.Key];
                if (cobject == null || !key.Equals(cobject[pivot.Key]) && cobject.Count > 0)
                {
                    cobject = new ExpandoObject();
                    cobject.Add(pivot.Key, key);
                    buckets.Add(cobject as ExpandoObject);
                }

                // Same key, so lets create or accumulate
                var column = itm[pivot.Columns];
                if (!cobject.ContainsKey(column.ToString()))
                {
                    cobject.Add(column.ToString(), new List <Object>()
                    {
                        itm[pivot.Value]
                    });
                }
                else
                {
                    var cvalue = cobject[column.ToString()] as List <Object>;
                    var avalue = itm[pivot.Value];
                    cvalue.Add(avalue);
                }
            }

            // Now we have our buckets, we want to apply our aggregation function
            var colNames   = new List <String>();
            var aggBuckets = new List <ExpandoObject>();

            foreach (IDictionary <String, Object> itm in buckets.ToArray())
            {
                var newItm = new ExpandoObject() as IDictionary <String, Object>;
                foreach (var value in itm)
                {
                    if (value.Key == pivot.Key)
                    {
                        newItm[pivot.Key] = value.Value;
                        continue; // Don't de-bucket the object
                    }

                    var bucket = (value.Value as IEnumerable <Object>);
                    newItm[value.Key] = this.Aggregate((value.Value as List <Object>), pivot.AggregateFunction);
                    if (!colNames.Contains(value.Key))
                    {
                        colNames.Add(value.Key);
                    }
                }
                aggBuckets.Add(newItm as ExpandoObject);
            }

            // Add where necessary
            var output = new List <ExpandoObject>();

            foreach (IDictionary <String, Object> itm in aggBuckets)
            {
                var tuple = (new ExpandoObject() as IDictionary <String, Object>);
                tuple[pivot.Key] = itm[pivot.Key];
                foreach (var col in colNames)
                {
                    if (itm.ContainsKey(col))
                    {
                        tuple[col] = itm[col];
                    }
                    else
                    {
                        tuple[col] = null;
                    }
                }
                output.Add(tuple as ExpandoObject);
            }

            return(new BisResultContext(context.QueryDefinition, context.Arguments, context.DataSource, output, context.StartTime.DateTime));
        }