Beispiel #1
0
        /// <summary>
        /// Computes a time-sensitive count aggregate of the non-null values using snapshot semantics.
        /// </summary>
        public IAggregate <TSource, ulong, ulong> CountNotNull <TValue>(Expression <Func <TSource, TValue> > selector)
        {
            Invariant.IsNotNull(selector, nameof(selector));
            var aggregate = new CountAggregate <TValue>();

            return(aggregate.SkipNulls().Wrap(selector).ApplyFilter(this.Filter));
        }
Beispiel #2
0
        /// <summary>
        /// Computes a time-sensitive count aggregate using snapshot semantics.
        /// </summary>
        public IAggregate <TSource, ulong, ulong> Count()
        {
            var aggregate = new CountAggregate <TSource>();

            return(aggregate.ApplyFilter(this.Filter));
        }
Beispiel #3
0
        internal static List <Entity> ProcessAggregateFetchXml(XrmFakedContext ctx, XDocument xmlDoc, List <Entity> resultOfQuery)
        {
            // Validate that <all-attributes> is not present,
            // that all attributes have groupby or aggregate, and an alias,
            // and that there is exactly 1 groupby.
            if (RetrieveFetchXmlNode(xmlDoc, "all-attributes") != null)
            {
                throw new Exception("Can't have <all-attributes /> present when using aggregate");
            }

            var ns = xmlDoc.Root.Name.Namespace;

            var entityName = RetrieveFetchXmlNode(xmlDoc, "entity")?.GetAttribute("name")?.Value;

            if (string.IsNullOrEmpty(entityName))
            {
                throw new Exception("Can't find entity name for aggregate query");
            }

            var aggregates = new List <FetchAggregate>();
            var groups     = new List <FetchGrouping>();

            foreach (var attr in xmlDoc.Descendants(ns + "attribute"))
            {
                //TODO: Find entity alias. Handle aliasedvalue in the query result.

                var alias       = attr.GetAttribute("alias")?.Value;
                var logicalName = attr.GetAttribute("name")?.Value;
                if (string.IsNullOrEmpty("alias"))
                {
                    throw new Exception("Missing alias for attribute in aggregate fetch xml");
                }
                if (string.IsNullOrEmpty("name"))
                {
                    throw new Exception("Missing name for attribute in aggregate fetch xml");
                }

                if (attr.IsAttributeTrue("groupby"))
                {
                    var dategrouping = attr.GetAttribute("dategrouping")?.Value;
                    if (dategrouping != null)
                    {
                        DateGroupType t;
                        if (!Enum.TryParse(dategrouping, true, out t))
                        {
                            throw new Exception("Unknown dategrouping value '" + dategrouping + "'");
                        }
                        groups.Add(new DateTimeGroup()
                        {
                            Type        = t,
                            OutputAlias = alias,
                            Attribute   = logicalName
                        });
                    }
                    else
                    {
                        groups.Add(new SimpleValueGroup()
                        {
                            OutputAlias = alias,
                            Attribute   = logicalName
                        });
                    }
                }
                else
                {
                    var agrFn = attr.GetAttribute("aggregate")?.Value;
                    if (string.IsNullOrEmpty(agrFn))
                    {
                        throw new Exception("Attributes must have be aggregated or grouped by when using aggregation");
                    }

                    FetchAggregate newAgr = null;
                    switch (agrFn?.ToLower())
                    {
                    case "count":
                        newAgr = new CountAggregate();
                        break;

                    case "countcolumn":
                        if (attr.IsAttributeTrue("distinct"))
                        {
                            newAgr = new CountDistinctAggregate();
                        }
                        else
                        {
                            newAgr = new CountColumnAggregate();
                        }
                        break;

                    case "min":
                        newAgr = new MinAggregate();
                        break;

                    case "max":
                        newAgr = new MaxAggregate();
                        break;

                    case "avg":
                        newAgr = new AvgAggregate();
                        break;

                    case "sum":
                        newAgr = new SumAggregate();
                        break;

                    default:
                        throw new Exception("Unknown aggregate function '" + agrFn + "'");
                    }

                    newAgr.OutputAlias = alias;
                    newAgr.Attribute   = logicalName;
                    aggregates.Add(newAgr);
                }
            }

            List <Entity> aggregateResult;

            if (groups.Any())
            {
                aggregateResult = ProcessGroupedAggregate(entityName, resultOfQuery, aggregates, groups);
            }
            else
            {
                aggregateResult = new List <Entity>();
                var ent = ProcessAggregatesForSingleGroup(entityName, resultOfQuery, aggregates);
                aggregateResult.Add(ent);
            }

            return(OrderAggregateResult(xmlDoc, aggregateResult.AsQueryable()));
        }