private void ExecuteAggregate(IDictionary<string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary<string, Type> parameterTypes, IDictionary<string, object> parameterValues, Dictionary<string, AggregateFunction> aggregates, ConcurrentDictionary<Entity, Dictionary<string, AggregateFunctionState>> groups, FetchXmlScan fetchXmlNode, SqlDateTime minValue, SqlDateTime maxValue) { parameterValues["@PartitionStart"] = minValue; parameterValues["@PartitionEnd"] = maxValue; var results = fetchXmlNode.Execute(dataSources, options, parameterTypes, parameterValues); foreach (var entity in results) { // Update aggregates var values = groups.GetOrAdd(entity, _ => ResetAggregates(aggregates)); lock (values) { foreach (var func in values.Values) func.AggregateFunction.NextPartition(entity, func.State); } } }
private SqlDateTime GetMinMaxKey(FetchXmlScan fetchXmlNode, IDictionary<string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary<string, Type> parameterTypes, IDictionary<string, object> parameterValues, bool max) { // Create a new FetchXmlScan node with a copy of the original query var minMaxNode = new FetchXmlScan { Alias = "minmax", DataSource = fetchXmlNode.DataSource, FetchXml = CloneFetchXml(fetchXmlNode.FetchXml), Parent = this }; // Remove the aggregate settings and all attributes from the query minMaxNode.FetchXml.aggregate = false; RemoveAttributesAndOrders(minMaxNode.Entity); // Add the primary key attribute of the root entity minMaxNode.Entity.AddItem(new FetchAttributeType { name = "createdon" }); // Sort by the primary key minMaxNode.Entity.AddItem(new FetchOrderType { attribute = "createdon", descending = max }); // Only need to retrieve the first item minMaxNode.FetchXml.top = "1"; try { var result = minMaxNode.Execute(dataSources, options, parameterTypes, parameterValues).FirstOrDefault(); if (result == null) return SqlDateTime.Null; return (SqlDateTime)result["minmax.createdon"]; } catch (QueryExecutionException ex) { ex.Node = this; throw; } }