Пример #1
0
        /// <summary>
        /// Sets the paging info in a FetchXML query
        /// </summary>
        /// <param name="fe">The expression of a FetchXML query</param>
        /// <param name="pagingCookie">The paging cookie string to set in the FetchXML query</param>
        /// <param name="pageNumber">The page number to set in the FetchXML query</param>
        /// <param name="count">The page size (count) to set in the FetchXML query</param>
        ///  <remarks>
        /// If top count is greater than 0, skips page setup and assumes query should only return TOP(X) results
        /// </remarks>
        public static void SetPage(this FetchExpression fe, string pagingCookie, int pageNumber, int count)
        {
            XElement fetchXml = fe.ToXml();

            fetchXml.SetFetchXmlPage(pagingCookie, pageNumber, count);

            fe.Query = fetchXml.ToString();
        }
Пример #2
0
        /// <summary>
        /// Performs an iterative series of RetrieveMultiple requests using FetchExpression in order to obtain all pages of results up to the provided maximum result count
        /// </summary>
        /// <param name="service">The current IOrganizationService instance</param>
        /// <param name="fetch">The FetchExpression query to be executed</param>
        /// <param name="shouldRetrieveAllPages">True = perform iterative paged query requests, otherwise return first page only</param>
        /// <param name="maxResultCount">An upper limit on the maximum number of entity records that should be retrieved as the query results - useful when the total size of result set is unknown and size may cause OutOfMemoryException</param>
        /// <param name="pagedOperation">An operation to perform on each page of results as it's retrieved</param>
        /// <returns>An EntityCollection containing the results of the query. Details reflect the last page retrieved (e.g. MoreRecords, PagingCookie, etc.)</returns>
        /// <remarks>
        /// CRM limits query response to paged result sets of 5,000. This method encapsulates the logic for performing subsequent
        /// query requests so that all results can be retrieved.
        /// </remarks>
        private static EntityCollection RetrieveMultiple(this IOrganizationService service, FetchExpression fetch, bool shouldRetrieveAllPages, long maxResultCount, Action <EntityCollection> pagedOperation)
        {
            XElement fetchXml   = fetch.ToXml();
            int      pageNumber = fetchXml.GetFetchXmlPageNumber();
            string   pageCookie = fetchXml.GetFetchXmlPageCookie();
            int      pageSize   = fetchXml.GetFetchXmlPageSize(QueryExtensions.DefaultPageSize);

            // Establish the first page based on lesser of initial/default page size or max result count (will be skipped if top count > 0)
            if (pageSize > maxResultCount)
            {
                pageSize = Convert.ToInt32(maxResultCount);
            }

            if (pageNumber <= 1 ||
                String.IsNullOrWhiteSpace(pageCookie))
            {
                // Ensure start with first page
                fetchXml.SetFetchXmlPage(null, 1, pageSize);
            }
            else
            {
                // Start with specified page
                fetchXml.SetFetchXmlPage(pageCookie, pageNumber, pageSize);
            }

            fetch.Query = fetchXml.ToString();

            // Track local long value to avoid expensive IEnumerable<T>.LongCount() method calls
            long totalResultCount = 0;
            var  allResults       = new EntityCollection();

            while (true)
            {
                // Retrieve the page
                EntityCollection page = service.RetrieveMultiple(fetch);

                // Capture the page
                if (totalResultCount == 0)
                {
                    // First page
                    allResults = page;
                }
                else
                {
                    allResults.Entities.AddRange(page.Entities);
                }

                // Invoke the paged operation if non-null
                pagedOperation?.Invoke(page);

                // Update the count of pages retrieved and processed
                totalResultCount = totalResultCount + page.Entities.Count;

                // Determine if we should retrieve the next page
                if (shouldRetrieveAllPages &&
                    totalResultCount < maxResultCount &&
                    page.MoreRecords)
                {
                    // Setup for next page
                    pageNumber++;

                    long remainder = maxResultCount - totalResultCount;

                    // If max result count is not divisible by page size, then final page may be less than the current page size and should be sized to remainder.
                    // No risk of coversion overflow.
                    if (pageSize > remainder)
                    {
                        pageSize = Convert.ToInt32(remainder);
                    }

                    fetch.SetPage(page.PagingCookie, pageNumber, pageSize);
                }
                else
                {
                    allResults.CopyFrom(page);
                    break;
                }
            }

            return(allResults);
        }
Пример #3
0
        /// <summary>
        /// Gets the page size specified in the 'count' attribute of a FetchXML query
        /// </summary>
        /// <param name="fe">The expression of a FetchXML query</param>
        /// <param name="defaultPageSize">The default page size to return if not found in the FetchXML query</param>
        /// <returns>The fetch count as an integer value</returns>
        public static int GetPageSize(this FetchExpression fe, int defaultPageSize)
        {
            XElement fetchXml = fe.ToXml();

            return(fetchXml.GetFetchXmlPageSize(defaultPageSize));
        }