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)); }