private EntityCollection GetExistingSolutions(IExecutionContainer container) { var cSolutions = container.RetrieveMultiple("solution", new string[] { "isvisible" }, new object[] { true }, new ColumnSet("solutionid", "uniquename", "friendlyname", "version", "ismanaged")); return(cSolutions); }
private EntityCollection GetAllRecordsForMatching(IExecutionContainer container, List <string> allattributes, Entity cdEntity) { container.StartSection(MethodBase.GetCurrentMethod().Name); var qMatch = new QueryExpression(cdEntity.LogicalName) { ColumnSet = new ColumnSet(allattributes.ToArray()) }; #if DEBUG container.Log($"Retrieving all records for {cdEntity.LogicalName}:\n{container.ConvertToFetchXml(qMatch)}"); #endif var matches = container.RetrieveMultiple(qMatch); SendLine(container, $"Pre-retrieved {matches.Count()} records for matching"); container.EndSection(); return(matches); }
private Tuple <int, int, int, int, int, EntityReferenceCollection> ImportDataBlock(IExecutionContainer container, DataBlock block, EntityCollection cEntities) { container.StartSection("ImportDataBlock"); var created = 0; var updated = 0; var skipped = 0; var deleted = 0; var failed = 0; var references = new EntityReferenceCollection(); var name = block.Name; container.Log($"Block: {name}"); SendStatus(name, null); SendLine(container); if (block.Import != null) { var includeid = block.Import.CreateWithId; var save = block.Import.Save; var delete = block.Import.Delete; var updateinactive = block.Import.UpdateInactive; var updateidentical = block.Import.UpdateIdentical; if (block.Import.OverwriteSpecified) { SendLine(container, "DEPRECATED use of attribute Overwrite!"); save = block.Import.Overwrite ? SaveTypes.CreateUpdate : SaveTypes.CreateOnly; } var matchattributes = GetMatchAttributes(block.Import.Match); var updateattributes = !updateidentical?GetUpdateAttributes(cEntities) : new List <string>(); var preretrieveall = block.Import.Match?.PreRetrieveAll == true; SendLine(container); SendLine(container, $"Importing block {name} - {cEntities.Count()} records "); var i = 1; if (delete == DeleteTypes.All && (matchattributes.Count == 0)) { // All records shall be deleted, no match attribute defined, so just get all and delete all var entity = block.Entity; var qDelete = new QueryExpression(entity); qDelete.ColumnSet.AddColumn(container.Entity(entity).PrimaryNameAttribute); var deleterecords = container.RetrieveMultiple(qDelete); //var deleterecords = Entity.RetrieveMultiple(crmsvc, qDelete, log); SendLine(container, $"Deleting ALL {entity} - {deleterecords.Count()} records"); foreach (var record in deleterecords.Entities) { SendLine(container, "{0:000} Deleting existing: {1}", i, record); try { container.Delete(record); deleted++; } catch (FaultException <OrganizationServiceFault> ex) { if (ex.Message.ToUpperInvariant().Contains("DOES NOT EXIST")) { // This may happen through delayed cascade delete in CRM SendLine(container, " ...already deleted"); } else { throw; } } i++; } } var totalRecords = cEntities.Count(); i = 1; EntityCollection cAllRecordsToMatch = null; foreach (var cdEntity in cEntities.Entities) { var unique = cdEntity.Id.ToString(); SendStatus(-1, -1, totalRecords, i); try { var oldid = cdEntity.Id; var newid = Guid.Empty; ReplaceGuids(container, cdEntity, includeid); ReplaceUpdateInfo(cdEntity); unique = GetEntityDisplayString(container, block.Import.Match, cdEntity); SendStatus(null, unique); if (!block.TypeSpecified || block.Type == EntityTypes.Entity) { #region Entity if (matchattributes.Count == 0) { if (save == SaveTypes.Never || save == SaveTypes.UpdateOnly) { skipped++; SendLine(container, "{0:000} Not saving: {1}", i, unique); } else { if (!includeid) { cdEntity.Id = Guid.Empty; } if (SaveEntity(container, cdEntity, null, updateinactive, updateidentical, i, unique)) { created++; newid = cdEntity.Id; references.Add(cdEntity.ToEntityReference()); } } } else { var matches = GetMatchingRecords(container, cdEntity, matchattributes, updateattributes, preretrieveall, ref cAllRecordsToMatch); if (delete == DeleteTypes.All || (matches.Count() == 1 && delete == DeleteTypes.Existing)) { foreach (var cdMatch in matches.Entities) { SendLine(container, "{0:000} Deleting existing: {1}", i, unique); try { container.Delete(cdMatch); deleted++; } catch (FaultException <OrganizationServiceFault> ex) { if (ex.Message.ToUpperInvariant().Contains("DOES NOT EXIST")) { // This may happen through cascade delete in CRM SendLine(container, " ...already deleted"); } else { throw; } } } matches.Entities.Clear(); } if (matches.Count() == 0) { if (save == SaveTypes.Never || save == SaveTypes.UpdateOnly) { skipped++; SendLine(container, "{0:000} Not creating: {1}", i, unique); } else { if (!includeid) { cdEntity.Id = Guid.Empty; } if (SaveEntity(container, cdEntity, null, updateinactive, updateidentical, i, unique)) { created++; newid = cdEntity.Id; references.Add(cdEntity.ToEntityReference()); } } } else if (matches.Count() == 1) { var match = matches[0]; newid = match.Id; if (save == SaveTypes.CreateUpdate || save == SaveTypes.UpdateOnly) { if (SaveEntity(container, cdEntity, match, updateinactive, updateidentical, i, unique)) { updated++; references.Add(cdEntity.ToEntityReference()); } else { skipped++; } } else { skipped++; SendLine(container, "{0:000} Exists: {1}", i, unique); } } else { failed++; SendLine(container, $"Import object matches {matches.Count()} records in target database!"); SendLine(container, unique); } } if (!oldid.Equals(Guid.Empty) && !newid.Equals(Guid.Empty) && !oldid.Equals(newid) && !guidmap.ContainsKey(oldid)) { container.Log("Mapping IDs: {0} ==> {1}", oldid, newid); guidmap.Add(oldid, newid); } #endregion Entity } else if (block.Type == EntityTypes.Intersect) { #region Intersect if (cdEntity.Attributes.Count != 2) { throw new ArgumentOutOfRangeException("Attributes", cdEntity.Attributes.Count, "Invalid Attribute count for intersect object"); } var intersect = block.IntersectName; if (string.IsNullOrEmpty(intersect)) { intersect = cdEntity.LogicalName; } var ref1 = (EntityReference)cdEntity.Attributes.ElementAt(0).Value; var ref2 = (EntityReference)cdEntity.Attributes.ElementAt(1).Value; var party1 = new Entity(ref1.LogicalName, ref1.Id); //Entity.InitFromNameAndId(ref1.LogicalName, ref1.Id, crmsvc, log); var party2 = new Entity(ref2.LogicalName, ref2.Id); //Entity.InitFromNameAndId(ref2.LogicalName, ref2.Id, crmsvc, log); try { container.Associate(party1, party2, intersect); //party1.Associate(party2, intersect); created++; SendLine(container, "{0} Associated: {1}", i.ToString().PadLeft(3, '0'), name); } catch (Exception ex) { if (ex.Message.Contains("duplicate")) { SendLine(container, "{0} Association exists: {1}", i.ToString().PadLeft(3, '0'), name); skipped++; } else { throw; } } #endregion Intersect } } catch (Exception ex) { failed++; SendLine(container, $"\n*** Error record: {unique} ***\n{ex.Message}"); container.Log(ex); if (stoponerror) { throw; } } i++; } SendLine(container, $"Created: {created} Updated: {updated} Skipped: {skipped} Deleted: {deleted} Failed: {failed}"); } container.EndSection(); return(new Tuple <int, int, int, int, int, EntityReferenceCollection>(created, updated, skipped, deleted, failed, references)); }
private EntityCollection GetMatchingRecords(IExecutionContainer container, Entity cdEntity, List <string> matchattributes, List <string> updateattributes, bool preretrieveall, ref EntityCollection cAllRecordsToMatch) { container.StartSection(MethodBase.GetCurrentMethod().Name); EntityCollection matches = null; var allattributes = new List <string> { container.Entity(cdEntity.LogicalName).PrimaryIdAttribute }; if (cdEntity.Contains("ownerid")) { allattributes.Add("ownerid"); } if (cdEntity.Contains("statecode") || cdEntity.Contains("statuscode")) { allattributes.Add("statecode"); allattributes.Add("statuscode"); } allattributes = allattributes.Union(matchattributes.Union(updateattributes)).ToList(); if (preretrieveall) { if (cAllRecordsToMatch == null) { cAllRecordsToMatch = GetAllRecordsForMatching(container, allattributes, cdEntity); } matches = GetMatchingRecordsFromPreRetrieved(container, matchattributes, cdEntity, cAllRecordsToMatch); } else { var qMatch = new QueryExpression(cdEntity.LogicalName) { // We need to be able to see if any attributes have changed, so lets make sure matching records have all the attributes that will be updated ColumnSet = new ColumnSet(allattributes.ToArray()) }; foreach (var matchattr in matchattributes) { object value = null; if (cdEntity.Contains(matchattr)) { value = container.AttributeAsBaseType(cdEntity, matchattr, null, false); } else if (matchattr == container.Entity(cdEntity.LogicalName).PrimaryIdAttribute) { value = cdEntity.Id; } if (value != null) { Query.AppendCondition(qMatch.Criteria, LogicalOperator.And, matchattr, Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal, value); } else { Query.AppendCondition(qMatch.Criteria, LogicalOperator.And, matchattr, Microsoft.Xrm.Sdk.Query.ConditionOperator.Null, null); } } #if DEBUG container.Log($"Finding matches for {cdEntity.LogicalName}:\n{container.ConvertToFetchXml(qMatch)}"); #endif matches = container.RetrieveMultiple(qMatch); } container.EndSection(); return(matches); }
private EntityCollection ExportDataBlock(IExecutionContainer container, ShuffleBlocks blocks, DataBlock block) { container.StartSection("ExportDataBlock"); container.Log($"Block: {block.Name}"); EntityCollection cExportEntities = null; if (block.Export != null) { #region Define attributes var attributes = block.Export.Items.Where(i => i is DataBlockExportAttributes).FirstOrDefault() as DataBlockExportAttributes; var allcolumns = false; var lAttributes = new List <string>(); var lNullAttributes = new List <string>(); if (attributes != null) { foreach (var attribute in attributes.Attribute) { var attr = attribute.Name; container.Log($"Adding column: {attr}"); lAttributes.Add(attr.Replace("*", "%")); if (attr.Contains("*")) { allcolumns = true; container.Log("Found wildcard"); } else { if (attribute.IncludeNull) { lNullAttributes.Add(attr); } } } } else { allcolumns = true; lAttributes.Add("*"); container.Log("Attributes not specified, retrieving all"); } #endregion Define attributes var fetchxml = block.Export.Items.Where(i => i is string).FirstOrDefault() as string; if (!string.IsNullOrWhiteSpace(fetchxml)) { container.StartSection("Export entity using FetchXML"); #if DEBUG container.Log($"FetchXML:\n{fetchxml}"); #endif cExportEntities = container.RetrieveMultiple(new FetchExpression(fetchxml)); container.EndSection(); } else if (!block.TypeSpecified || block.Type == EntityTypes.Entity) { #region QueryExpression Entity container.StartSection($"Export entity {block.Entity}"); var qExport = new QueryExpression(block.Entity); if (block.Export.ActiveOnly) { Query.AppendConditionActive(qExport.Criteria); //CintQryExp.AppendConditionActive(qExport.Criteria); } if (block.Relation != null) { foreach (var relation in block.Relation) { AddRelationFilter(container, blocks, block.Entity, relation, qExport.Criteria); } } foreach (var filter in block.Export.Items.Where(i => i is DataBlockExportFilter).Cast <DataBlockExportFilter>()) { AddFilter(container, qExport, filter); } foreach (var sort in block.Export.Items.Where(i => i is DataBlockExportSort).Cast <DataBlockExportSort>()) { qExport.AddOrder(sort.Attribute, sort.Type == SortTypes.Desc ? OrderType.Descending : OrderType.Ascending); } if (allcolumns) { qExport.ColumnSet = new ColumnSet(true); } else { foreach (var attr in lAttributes) { qExport.ColumnSet.AddColumn(attr); } } #if DEBUG container.Log("Converting to FetchXML"); try { var fetch = container.ConvertToFetchXml(qExport); container.Log($"Exporting {block.Entity}:\n{fetch}"); } catch (Exception ex) { container.Log("Conversion error:"); container.Log(ex); } #endif cExportEntities = container.RetrieveMultiple(qExport); if (allcolumns) { SelectAttributes(container, cExportEntities, lAttributes, lNullAttributes); } SendLine(container, $"Block {block.Name} - {cExportEntities.Count()} records"); container.EndSection(); #endregion QueryExpression Entity } else if (block.Type == EntityTypes.Intersect) { #region FetchXML Intersect container.StartSection($"Export intersect {block.Entity}"); var xDoc = new XmlDocument(); var xEntity = FetchXML.Create(xDoc, block.Entity); FetchXML.AddAttribute(xEntity, lAttributes.ToArray()); if (block.Relation != null) { foreach (var relation in block.Relation) { AddRelationFilter(container, blocks, relation, xEntity); } } var fetch = xDoc.OuterXml; //Imran: Removed because this is causing invalid Xml errors. Could not see the point of having these placeholders. //fetch = fetch.Replace("<fetch ", "<fetch {0} {1} "); // Detta för att se till att CrmServiceProxy.RetrieveMultiple kan hantera paging #if DEBUG container.Log($"Exporting intersect entity {block.Entity}\n{fetch}"); #endif var qExport = new FetchExpression(fetch); cExportEntities = container.RetrieveMultiple(qExport); foreach (var entity in cExportEntities.Entities) { var newattributes = new List <KeyValuePair <string, object> >(); foreach (var attr in entity.Attributes) { if (attr.Value is Guid guid) { var attrname = attr.Key; var relatedentity = attrname.Substring(0, attrname.Length - (attrname.EndsWith("idone") || attrname.EndsWith("idtwo") ? 5 : 2)); if (!newattributes.Contains(new KeyValuePair <string, object>(attrname, new EntityReference(relatedentity, guid)))) { container.Log($"Adding Attribute {attrname} - Related entity {relatedentity}"); newattributes.Add(new KeyValuePair <string, object>(attrname, new EntityReference(relatedentity, guid))); #if DEBUG container.Log($"{attrname} added"); #endif } else { #if DEBUG container.Log($"{attrname} already exists."); #endif } } } foreach (var newattr in newattributes) { #if DEBUG container.Log($"Entity {entity.LogicalName} contains attribute {newattr.Key}: {entity.Attributes.Contains(newattr.Key)}"); #endif if (!entity.Attributes.Contains(newattr.Key)) { entity.Attributes.Add(newattr.Key, newattr.Value); } } } container.EndSection(); #endregion FetchXML Intersect } container.Log($"Returning {cExportEntities.Count()} records"); } container.EndSection(); return(cExportEntities); }