protected override void ExecuteLogic() { // get the triggering record var target = Target.ToEntity <NotificationMessage>(); if (target.Regarding != null) { target.RegardingTypeCode = MetadataHelpers .GetEntityAttribute <int>(Service, target.Regarding.LogicalName, MetadataHelpers.EntityAttribute.ObjectTypeCode, Context.OrganizationId); } }
public string GetIdFieldName(string logicalName) { var key = $"MetaDataHelper.GetIdFieldName|{logicalName}"; var cachedEntityMetaData = GetFromMemCache <string>(key); if (cachedEntityMetaData != null) { return(cachedEntityMetaData); } var idFieldName = MetadataHelpers .GetEntityAttribute <string>(service, logicalName, MetadataHelpers.EntityAttribute.PrimaryIdAttribute, CrmService.OrgId); return(AddToMemCache(key, idFieldName)); }
public IEnumerable <string> GetAlternateKeys(string logicalName) { var key = $"MetaDataHelper.GetAlternateKeys|{logicalName}"; var cachedEntityMetaData = GetFromMemCache <IEnumerable <string> >(key); if (cachedEntityMetaData != null) { return(cachedEntityMetaData); } var retrievedMetaData = MetadataHelpers .GetEntityAttribute <EntityKeyMetadata[]>(service, logicalName, MetadataHelpers.EntityAttribute.Keys, CrmService.OrgId); return(AddToMemCache(key, retrievedMetaData?.SelectMany(m => m.KeyAttributes ?? new string[0]))); }
private IEnumerable <EntityReference> GetFilteredRecords(string logicalName, IEnumerable <ExportedEntityDefinition> recordDefinitions, RecordsFilterMode mode) { log.Log($"Getting filtered records ..."); var uniqueRecords = new List <EntityReference>(); log.Log($"Getting existing records for '{logicalName}'..."); log.Log($"Getting ID field name ..."); var idField = MetadataHelpers .GetEntityAttribute <string>(service, logicalName, MetadataHelpers.EntityAttribute.PrimaryIdAttribute, CrmService.OrgId); log.Log($"ID field name: {idField}."); log.Log($"Getting alternate key names ..."); var alternateKeys = metadataHelper.GetAlternateKeys(logicalName).ToArray(); log.Log($"Found {alternateKeys.Length} keys."); var definitions = recordDefinitions.ToArray(); var idDefinitions = definitions.Where(d => !d.IsUseAlternateKeys || !d.Record.KeyAttributes.Any()).ToArray(); var alternateKeyDefinitions = definitions.Where(d => d.IsUseAlternateKeys && d.Record.KeyAttributes.Any()).ToArray(); Parallel.ForEach(idDefinitions.GroupBy(d => d.QueryKey), new ParallelOptions { MaxDegreeOfParallelism = CrmService.Threads }, group => { queries.TryGetValue(group.Key, out var fetchXml); fetchXml = BuildExistingRecordsFetchXml(fetchXml, idField); foreach (var relationKey in group.GroupBy(g => g.RelationId, g => g).Select(g => g.Key)) { var updatedFetchXml = UpdateRelatedConditionInFetchXml(fetchXml, relationKey); var existingRecords = RetrieveRecords(updatedFetchXml); switch (mode) { case RecordsFilterMode.UniqueInDestination: uniqueRecords.AddRange(existingRecords.Select(r => r.Id).Except(group.Select(d => d.Record.Id)) .Select(id => new EntityReference(logicalName, id))); break; case RecordsFilterMode.UniqueInSource: uniqueRecords.AddRange(group.Select(d => d.Record.Id).Except(existingRecords.Select(r => r.Id)) .Select(id => new EntityReference(logicalName, id))); break; case RecordsFilterMode.Common: uniqueRecords.AddRange(group.Select(d => d.Record.Id).Intersect(existingRecords.Select(r => r.Id)) .Select(id => new EntityReference(logicalName, id))); break; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, "Unique records mode is out of range."); } } }); Parallel.ForEach(alternateKeyDefinitions.GroupBy(d => d.QueryKey), new ParallelOptions { MaxDegreeOfParallelism = CrmService.Threads }, group => { queries.TryGetValue(group.Key, out var fetchXml); fetchXml = BuildExistingRecordsFetchXml(fetchXml, idField, alternateKeys); foreach (var relationKey in group.GroupBy(g => g.RelationId, g => g).Select(g => g.Key)) { var updatedFetchXml = UpdateRelatedConditionInFetchXml(fetchXml, relationKey); var existingRecords = RetrieveRecords(updatedFetchXml); var exportedRecords = group.Select(d => d.Record); IEnumerable <Guid> existingExceptExportedIds; switch (mode) { case RecordsFilterMode.UniqueInDestination: existingExceptExportedIds = existingRecords .Where(r => exportedRecords.All(e => alternateKeys.All( a => { var firstValue = r.GetAttributeValue <object>(a); var secondValue = e.GetAttributeValue <object>(a); return((firstValue != null && secondValue != null && !firstValue.Equals(secondValue)) || (firstValue != secondValue)); }))) .Select(r => r.Id); break; case RecordsFilterMode.UniqueInSource: existingExceptExportedIds = exportedRecords .Where(r => existingRecords.All(e => alternateKeys.All( a => { var firstValue = r.GetAttributeValue <object>(a); var secondValue = e.GetAttributeValue <object>(a); return((firstValue != null && secondValue != null && !firstValue.Equals(secondValue)) || (firstValue != secondValue)); }))) .Select(r => r.Id); break; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, "Unique records mode is out of range."); } uniqueRecords.AddRange(existingExceptExportedIds .Select(id => new EntityReference(logicalName, id))); } }); log.Log($"Got existing records for '{logicalName}'. Count: {uniqueRecords.Count}"); return(uniqueRecords); }