public IEnumerable <CrmEntityIndexDocument> GetDocuments() { ADXTrace.Instance.TraceInfo(TraceCategory.Application, "Start"); var dataContext = _index.DataContext; var documentFactory = new FetchXmlIndexDocumentFactory(_index, _fetchXml, _titleAttributeLogicalName, _localeConfig); var currentPageFetchXml = _fetchXml; var knowledgeArticleFilter = new FetchXmlResultsFilter(); while (true) { var request = new OrganizationRequest("ExecuteFetch"); request.Parameters["FetchXml"] = currentPageFetchXml.ToString(); var response = dataContext.Execute(request); if (response == null) { throw new InvalidOperationException("Did not receive valid response from ExecuteFetchRequest."); } var fetchXmlResponse = response.Results["FetchXmlResult"] as string; if (FeatureCheckHelper.IsFeatureEnabled(FeatureNames.CmsEnabledSearching)) { if (this._fetchXml.LogicalName == "knowledgearticle") { fetchXmlResponse = knowledgeArticleFilter.Aggregate(fetchXmlResponse, "knowledgearticleid", "record2id.productid", "adx_contentaccesslevelid.adx_contentaccesslevelid", "record2id.connectionid", "annotation.filename", "annotation.notetext", "annotation.annotationid"); } if (this._fetchXml.LogicalName == "annotation") { fetchXmlResponse = knowledgeArticleFilter.Aggregate(fetchXmlResponse, "annotationid", "product.productid"); } } var resultSet = new FetchXmlResultSet(fetchXmlResponse); ADXTrace.Instance.TraceInfo(TraceCategory.Application, string.Format("FetchXmlResult:LogicalName={0}, Count={1}", EntityNamePrivacy.GetEntityName(this._fetchXml.LogicalName), resultSet.Count())); foreach (var document in resultSet.Select(documentFactory.GetDocument)) { yield return(document); } if (resultSet.MoreRecords) { currentPageFetchXml = currentPageFetchXml.ForNextPage(resultSet.PagingCookie); } else { break; } } ADXTrace.Instance.TraceInfo(TraceCategory.Application, "End"); }
/// <summary> /// Receives entire Fetch Xml and aggregates duplicate results caused by having N:N or 1:N relationships. /// </summary> /// <param name="fetchXml">The fetch XML.</param> /// <param name="primaryKeyFieldName">Entity Id field name</param> /// <param name="fields">List of fields</param> /// <returns>Aggregated results on Fetch Xml</returns> public string Aggregate(string fetchXml, string primaryKeyFieldName, params string[] fields) { var fetchXmlParsed = XDocument.Parse(fetchXml); var inputResults = fetchXmlParsed.Descendants("result").ToList(); if (inputResults.Count == 0) { return(fetchXml); } var aggregatedResults = new Dictionary <string, XElement>(); var parsedResultSet = new FetchXmlResultSet(fetchXml); bool isFirstPage = this.lastResultOnPage == null; bool isLastPage = !parsedResultSet.MoreRecords; //// Check if last result of last page and first result of this page are the same article. //// If not, we need to add the aggregated result from last page during this round. //// If so, the past CAL/product ids should still be stored and we'll just add to if (!isFirstPage) { var firstId = inputResults.First().Descendants(primaryKeyFieldName).FirstOrDefault().Value; var previousPageLastId = this.lastResultOnPage.Descendants(primaryKeyFieldName).FirstOrDefault().Value; if (firstId != previousPageLastId) { aggregatedResults[previousPageLastId] = this.lastResultOnPage; } } var lastId = inputResults.Descendants(primaryKeyFieldName).FirstOrDefault().Value; var collectionOfFields = fields.Select(fieldName => new RelatedField(fieldName)).ToList(); //// Iterating through fetchXml retrieving multiple related fields foreach (var resultNode in inputResults) { var primaryKeyFieldNode = resultNode.Descendants(primaryKeyFieldName).FirstOrDefault(); if (primaryKeyFieldNode == null) { return(fetchXml); } ////Retrieving fields collectionOfFields.ForEach(field => this.GetRelatedFields(resultNode, field, primaryKeyFieldNode.Value)); ////Removing duplicate nodes aggregatedResults[primaryKeyFieldNode.Value] = resultNode; } var node = inputResults.FirstOrDefault(); if (node == null) { return(fetchXml); } var parentNode = node.Parent; if (parentNode == null) { return(fetchXml); } fetchXmlParsed.Descendants("result").Remove(); //// Inserting retrieved above related fields and deduplicated results. collectionOfFields.ForEach(field => this.InsertRelatedFields(aggregatedResults, field)); //// Remove and store the last aggregated result, as this might be the same article as the first result on the //// next page. this.lastResultOnPage = aggregatedResults[lastId]; if (!isLastPage) { aggregatedResults.Remove(lastId); } fetchXmlParsed.Element(parentNode.Name).Add(aggregatedResults.Values); return(fetchXmlParsed.ToString()); }