private static void AddRelationFilter(ShuffleBlocks blocks, XmlNode xRelation, XmlNode xEntity, ILoggable log)
 {
     if (blocks != null && blocks.Count > 0)
     {
         var                     block       = CintXML.GetAttribute(xRelation, "Block");
         var                     attribute   = CintXML.GetAttribute(xRelation, "Attribute");
         var                     pkattribute = CintXML.GetAttribute(xRelation, "PK-Attribute");
         var                     includenull = CintXML.GetBoolAttribute(xRelation, "IncludeNull", false);
         List <string>           ids         = new List <string>();
         CintDynEntityCollection parentcoll  = blocks.ContainsKey(block) ? blocks[block] : null;
         if (parentcoll != null && parentcoll.Count > 0)
         {
             foreach (CintDynEntity parent in parentcoll)
             {
                 if (string.IsNullOrEmpty(pkattribute))
                 {
                     ids.Add(parent.Id.ToString());
                 }
                 else
                 {
                     ids.Add(parent.Property <EntityReference>(pkattribute, new EntityReference()).Id.ToString());
                 }
             }
         }
         else
         {
             // Adding temp guid to indicate "no matches", as ConditionOperator.In will fail if no values are given
             ids.Add(new Guid().ToString());
         }
         if (!includenull)
         {
             CintFetchXML.AppendFilter(xEntity, "and", attribute, "in", ids.ToArray());
         }
         else
         {
             var xFilter = CintFetchXML.AppendFilter(xEntity, "or");
             CintFetchXML.AppendCondition(xFilter, attribute, "null");
             CintFetchXML.AppendCondition(xFilter, attribute, "in", ids.ToArray());
         }
         log.Log("Adding relation condition for {0} in {1} values in {2}.{3}", attribute, ids.Count, block, pkattribute);
     }
 }
        private bool DoImportSolution(XmlNode xImport, string filename, Version version)
        {
            log.StartSection(MethodBase.GetCurrentMethod().Name);
            var       result       = false;
            bool      activatecode = CintXML.GetBoolAttribute(xImport, "ActivateServersideCode", false);
            bool      overwrite    = CintXML.GetBoolAttribute(xImport, "OverwriteCustomizations", false);
            Exception ex           = null;

            SendLine("Importing solution: {0} Version: {1}", filename, version);
            byte[] fileBytes = File.ReadAllBytes(filename);
            ImportSolutionRequest impSolReq = new ImportSolutionRequest()
            {
                CustomizationFile = fileBytes,
                OverwriteUnmanagedCustomizations = overwrite,
                PublishWorkflows = activatecode,
                ImportJobId      = Guid.NewGuid()
            };

            if (crmsvc is CrmServiceProxy && ((CrmServiceProxy)crmsvc).CrmVersion.Major >= 6)
            {   // CRM 2013 or later, import async
                result = DoImportSolutionAsync(impSolReq, ref ex);
            }
            else
            {   // Pre CRM 2013, import sync
                result = DoImportSolutionSync(impSolReq, ref ex);
            }
            if (!result && stoponerror)
            {
                if (ex != null)
                {
                    throw ex;
                }
                else
                {
                    throw new Exception("Solution import failed");
                }
            }
            log.Log("Returning: {0}", result);
            log.EndSection();
            return(result);
        }
        private SolutionImportConditions CheckIfImportRequired(XmlNode xImport, string name, Version thisversion)
        {
            log.StartSection("CheckIfImportRequired");
            SolutionImportConditions result = SolutionImportConditions.Create;
            bool overwritesame  = CintXML.GetBoolAttribute(xImport, "OverwriteSameVersion", true);
            bool overwritenewer = CintXML.GetBoolAttribute(xImport, "OverwriteNewerVersion", false);
            CintDynEntityCollection cSolutions = GetExistingSolutions();

            foreach (CintDynEntity cdSolution in cSolutions)
            {
                if (cdSolution.Property("uniquename", "") == name)
                {   // Now we have found the same solution in target environment
                    result = SolutionImportConditions.Update;
                    var existingversion = new Version(cdSolution.Property("version", "1.0.0.0"));
                    log.Log("Existing solution has version: {0}", existingversion);
                    var comparison = thisversion.CompareTo(existingversion);
                    if (!overwritesame && comparison == 0)
                    {
                        result = SolutionImportConditions.Skip;
                        SendLine("Solution {0} {1} already exists in target", name, thisversion);
                    }
                    else if (!overwritenewer && comparison < 0)
                    {
                        result = SolutionImportConditions.Skip;
                        SendLine("Existing solution {0} {1} is newer than {2}", name, existingversion, thisversion);
                    }
                    else if (existingversion == thisversion)
                    {
                        SendLine("Updating version {0}", thisversion);
                    }
                    else
                    {
                        SendLine("Replacing version {0} with {1}", existingversion, thisversion);
                    }
                    break;
                }
            }
            log.Log("Import Condition: {0}", result);
            log.EndSection();
            return(result);
        }
Exemple #4
0
        /// <summary>
        /// Import entities to CRM from dictionary of blocks
        /// </summary>
        /// <param name="blocks">Blocks with entities to import</param>
        /// <returns>Tuple with counters for: Created, Updated, Skipped and Failed records</returns>
        public Tuple <int, int, int, int, int, EntityReferenceCollection> ImportToCRM(ShuffleBlocks blocks)
        {
            log.StartSection("ImportToCRM");
            if (definition == null)
            {
                throw new ArgumentNullException("Definition", "Shuffle definition must be specified to import data");
            }

            int created = 0;
            int updated = 0;
            int skipped = 0;
            int deleted = 0;
            int failed  = 0;
            EntityReferenceCollection references = new EntityReferenceCollection();

            XmlNode xRoot   = CintXML.FindChild(definition, "ShuffleDefinition");
            XmlNode xBlocks = CintXML.FindChild(xRoot, "Blocks");

            if (xBlocks != null)
            {
                guidmap     = new Dictionary <Guid, Guid>();
                stoponerror = CintXML.GetBoolAttribute(xRoot, "StopOnError", false);
                timeout     = CintXML.GetIntAttribute(xRoot, "Timeout", -1);
                double savedtimeout = -1;
                if (timeout > -1)
                {
                    try
                    {
                        SendLine("Setting timeout: {0} minutes", timeout);
                        OrganizationServiceProxy orgsvcpxy = crmsvc.GetService <OrganizationServiceProxy>();
                        savedtimeout      = orgsvcpxy.Timeout.TotalMinutes;
                        orgsvcpxy.Timeout = new TimeSpan(0, timeout, 0);
                    }
                    catch (InvalidPluginExecutionException)
                    {   // Couldn't cast to correct service type, for some reason...
                        savedtimeout = -1;
                    }
                }

                int totalBlocks  = xBlocks.ChildNodes.Count;
                int currentBlock = 0;
                foreach (XmlNode xBlock in xBlocks.ChildNodes)
                {
                    currentBlock++;
                    SendStatus(totalBlocks, currentBlock, -1, -1);
                    if (xBlock.NodeType == XmlNodeType.Element)
                    {
                        switch (xBlock.Name)
                        {
                        case "DataBlock":
                            string name = CintXML.GetAttribute(xBlock, "Name");
                            if (!blocks.ContainsKey(name))
                            {
                                blocks.Add(name, new CintDynEntityCollection());
                            }
                            Tuple <int, int, int, int, int, EntityReferenceCollection> dataresult = ImportDataBlock(xBlock, blocks[name]);
                            created += dataresult.Item1;
                            updated += dataresult.Item2;
                            skipped += dataresult.Item3;
                            deleted += dataresult.Item4;
                            failed  += dataresult.Item5;
                            references.AddRange(dataresult.Item6);
                            break;

                        case "SolutionBlock":
                            var solutionresult = ImportSolutionBlock(xBlock);
                            switch (solutionresult)
                            {
                            case ItemImportResult.Created: created++; break;

                            case ItemImportResult.Updated: updated++; break;

                            case ItemImportResult.Skipped: skipped++; break;

                            case ItemImportResult.Failed: failed++; break;
                            }
                            break;
                        }
                    }
                }
                SendStatus(0, 0, 0, 0);
                if (savedtimeout > -1)
                {
                    OrganizationServiceProxy orgsvcpxy = crmsvc.GetService <OrganizationServiceProxy>();
                    orgsvcpxy.Timeout = new TimeSpan(0, (int)savedtimeout, 0);
                }
            }
            log.EndSection();
            return(new Tuple <int, int, int, int, int, EntityReferenceCollection>(created, updated, skipped, deleted, failed, references));
        }
Exemple #5
0
        /// <summary>
        /// Export entities from CRM to dictionary of blocks with entities
        /// </summary>
        /// <returns>Blocks with exported entities</returns>
        public ShuffleBlocks ExportFromCRM()
        {
            log.StartSection("ExportFromCRM");
            if (definition == null)
            {
                throw new ArgumentNullException("Definition", "Shuffle definition must be specified to export data");
            }
            ShuffleBlocks blocks = new ShuffleBlocks();

            ExistingSolutionVersions = null;
            XmlNode xRoot   = CintXML.FindChild(definition, "ShuffleDefinition");
            XmlNode xBlocks = CintXML.FindChild(xRoot, "Blocks");

            if (xBlocks != null)
            {
                stoponerror = CintXML.GetBoolAttribute(xRoot, "StopOnError", false);
                timeout     = CintXML.GetIntAttribute(xRoot, "Timeout", -1);
                double savedtimeout = -1;
                if (timeout > -1)
                {
                    SendLine("Setting timeout: {0} minutes", timeout);
                    OrganizationServiceProxy orgsvcpxy = crmsvc.GetService <OrganizationServiceProxy>();
                    savedtimeout      = orgsvcpxy.Timeout.TotalMinutes;
                    orgsvcpxy.Timeout = new TimeSpan(0, timeout, 0);
                }

                int totalBlocks  = xBlocks.ChildNodes.Count;
                int currentBlock = 0;
                foreach (XmlNode xBlock in xBlocks.ChildNodes)
                {
                    currentBlock++;
                    SendStatus(totalBlocks, currentBlock, -1, -1);
                    if (xBlock.NodeType == XmlNodeType.Element)
                    {
                        switch (xBlock.Name)
                        {
                        case "DataBlock":
                            CintDynEntityCollection cExported = ExportDataBlock(blocks, xBlock);
                            string name = CintXML.GetAttribute(xBlock, "Name");
                            if (cExported != null)
                            {
                                if (blocks.ContainsKey(name))
                                {
                                    SendLine("Block already added: {0}", name);
                                }
                                else
                                {
                                    blocks.Add(name, cExported);
                                }
                            }
                            break;

                        case "SolutionBlock":
                            if (ExistingSolutionVersions == null)
                            {
                                GetCurrentVersions();
                            }
                            ExportSolutionBlock(xBlock);
                            break;
                        }
                    }
                }
                SendStatus(0, 0, 0, 0);
                if (savedtimeout > -1)
                {
                    OrganizationServiceProxy orgsvcpxy = crmsvc.GetService <OrganizationServiceProxy>();
                    orgsvcpxy.Timeout = new TimeSpan(0, (int)savedtimeout, 0);
                }
            }
            log.EndSection();
            return(blocks);
        }
        private CintDynEntityCollection ExportDataBlock(ShuffleBlocks blocks, XmlNode xBlock)
        {
            log.StartSection("ExportDataBlock");
            string name = CintXML.GetAttribute(xBlock, "Name");

            log.Log("Block: {0}", name);
            CintDynEntityCollection cExportEntities = null;

            if (xBlock.Name != "DataBlock")
            {
                throw new ArgumentOutOfRangeException("Type", xBlock.Name, "Invalid Block type");
            }
            string  entity  = CintXML.GetAttribute(xBlock, "Entity");
            string  type    = CintXML.GetAttribute(xBlock, "Type");
            XmlNode xExport = CintXML.FindChild(xBlock, "Export");

            if (xExport != null)
            {
                if (string.IsNullOrEmpty(entity))
                {
                    entity = CintXML.GetAttribute(xExport, "Entity");
                }

                #region Define attributes

                XmlNode       xAttributes     = CintXML.FindChild(xExport, "Attributes");
                bool          allcolumns      = false;
                List <string> lAttributes     = new List <string>();
                List <string> lNullAttributes = new List <string>();
                if (xAttributes != null)
                {
                    foreach (XmlNode xAttr in xAttributes.ChildNodes)
                    {
                        if (xAttr.Name == "Attribute")
                        {
                            string attr = CintXML.GetAttribute(xAttr, "Name");
                            log.Log("Adding column: {0}", attr);
                            lAttributes.Add(attr.Replace("*", "%"));
                            if (attr.Contains("*"))
                            {
                                allcolumns = true;
                                log.Log("Found wildcard");
                            }
                            else
                            {
                                bool includenull = CintXML.GetBoolAttribute(xAttr, "IncludeNull", false);
                                if (includenull)
                                {
                                    lNullAttributes.Add(attr);
                                }
                            }
                        }
                    }
                }
                else
                {
                    allcolumns = true;
                    lAttributes.Add("*");
                    log.Log("Attributes not specified, retrieving all");
                }

                #endregion Define attributes

                if (type == "Entity" || string.IsNullOrEmpty(type))
                {
                    #region QueryExpression Entity

                    log.StartSection("Export entity " + entity);
                    QueryExpression qExport = new QueryExpression(entity);
                    if (CintXML.GetBoolAttribute(xExport, "ActiveOnly", true))
                    {
                        CintQryExp.AppendConditionActive(qExport.Criteria);
                    }

                    foreach (var xBlockChild in xBlock.ChildNodes.Cast <XmlNode>())
                    {
                        if (xBlockChild.Name == "Relation")
                        {
                            AddRelationFilter(blocks, xBlockChild, qExport.Criteria, log);
                        }
                    }
                    foreach (XmlNode xExpProp in xExport.ChildNodes)
                    {
                        if (xExport.NodeType == XmlNodeType.Element)
                        {
                            switch (xExpProp.Name)
                            {
                            case "#comment":
                            case "Attributes":
                                break;

                            case "Filter":
                                AddFilter(qExport, xExpProp);
                                break;

                            case "Sort":
                                qExport.AddOrder(
                                    CintXML.GetAttribute(xExpProp, "Attribute"),
                                    CintXML.GetAttribute(xExpProp, "Type") == "Desc" ? OrderType.Descending : OrderType.Ascending);
                                break;

                            default:
                                throw new ArgumentOutOfRangeException("Name", xExpProp.Name, "Invalid subitem to export block " + name);
                            }
                        }
                    }
                    if (allcolumns)
                    {
                        qExport.ColumnSet = new ColumnSet(true);
                    }
                    else
                    {
                        foreach (string attr in lAttributes)
                        {
                            qExport.ColumnSet.AddColumn(attr);
                        }
                    }
#if DEBUG
                    log.Log("Converting to FetchXML");
                    try
                    {
                        var fetch = CintQryExp.ConvertToFetchXml(qExport, crmsvc);
                        log.Log("Exporting {0}:\n{1}", entity, fetch);
                    }
                    catch (Exception ex)
                    {
                        log.Log("Conversion error:");
                        log.Log(ex);
                    }
#endif
                    cExportEntities = CintDynEntity.RetrieveMultiple(crmsvc, qExport, log);
                    if (allcolumns)
                    {
                        SelectAttributes(cExportEntities, lAttributes, lNullAttributes);
                    }
                    SendLine("Block {0} - {1} records", name, cExportEntities.Count);
                    log.EndSection();

                    #endregion QueryExpression Entity
                }
                else if (type == "Intersect")
                {
                    #region FetchXML Intersect

                    log.StartSection("Export intersect " + entity);
                    XmlDocument xDoc    = new XmlDocument();
                    XmlNode     xEntity = CintFetchXML.Create(xDoc, entity);
                    CintFetchXML.AddAttribute(xEntity, lAttributes.ToArray());

                    foreach (var xBlockChild in xBlock.ChildNodes.Cast <XmlNode>())
                    {
                        if (xBlockChild.Name == "Relation")
                        {
                            AddRelationFilter(blocks, xBlockChild, xEntity, log);
                        }
                    }

                    var fetch = xDoc.OuterXml;
                    fetch = fetch.Replace("<fetch ", "<fetch {0} {1} ");    // Detta för att se till att CrmServiceProxy.RetrieveMultiple kan hantera paging
#if DEBUG
                    log.Log("Exporting intersect entity {0}\n{1}", entity, fetch);
#endif
                    var qExport = new FetchExpression(fetch);
                    cExportEntities = CintDynEntity.RetrieveMultiple(crmsvc, qExport, log);
                    foreach (var cde in cExportEntities)
                    {
                        List <KeyValuePair <string, object> > newattributes = new List <KeyValuePair <string, object> >();
                        foreach (var attr in cde.Attributes)
                        {
                            if (attr.Value is Guid)
                            {
                                var    attrname      = attr.Key;
                                string relatedentity = attrname.Substring(0, attrname.Length - (attrname.EndsWith("idone") || attrname.EndsWith("idtwo") ? 5 : 2));
                                newattributes.Add(new KeyValuePair <string, object>(attrname, new EntityReference(relatedentity, (Guid)attr.Value)));
                            }
                        }
                        foreach (var newattr in newattributes)
                        {
                            if (!newattr.Key.Equals(cde.PrimaryIdAttribute))
                            {
                                cde.AddProperty(newattr.Key, newattr.Value);
                            }
                        }
                    }
                    log.EndSection();

                    #endregion FetchXML Intersect
                }

                log.Log("Returning {0} records", cExportEntities.Count);
            }
            log.EndSection();
            return(cExportEntities);
        }
        private void AddRelationFilter(ShuffleBlocks blocks, XmlNode xRelation, FilterExpression filter, ILoggable log)
        {
            log.StartSection(MethodBase.GetCurrentMethod().Name);
            if (blocks != null && blocks.Count > 0)
            {
                var block       = CintXML.GetAttribute(xRelation, "Block");
                var attribute   = CintXML.GetAttribute(xRelation, "Attribute");
                var pkattribute = CintXML.GetAttribute(xRelation, "PK-Attribute");
                var includenull = CintXML.GetBoolAttribute(xRelation, "IncludeNull", false);
                var entityName  = xRelation.ParentNode.Attributes["Entity"].Value;

                var type = GetAttributeType(attribute, entityName);

                ConditionExpression cond = new ConditionExpression();
                cond.AttributeName = attribute;
                cond.Operator      = Microsoft.Xrm.Sdk.Query.ConditionOperator.In;

                List <object>           ids        = new List <object>();
                CintDynEntityCollection parentcoll = blocks.ContainsKey(block) ? blocks[block] : null;
                if (parentcoll != null && parentcoll.Count > 0)
                {
                    foreach (CintDynEntity parent in parentcoll)
                    {
                        if (string.IsNullOrEmpty(pkattribute))
                        {
                            if (type == AttributeTypeCode.String)
                            {
                                ids.Add(parent.Id.ToString());
                            }
                            else
                            {
                                ids.Add(parent.Id);
                            }
                        }
                        else if (type == AttributeTypeCode.String)
                        {
                            ids.Add(parent.Property <EntityReference>(pkattribute, new EntityReference()).Id.ToString());
                        }
                        else
                        {
                            ids.Add(parent.Property <EntityReference>(pkattribute, new EntityReference()).Id);
                        }
                    }
                }
                else
                {
                    // Adding temp guid to indicate "no matches", as ConditionOperator.In will fail if no values are given
                    ids.Add(new Guid());
                }
                cond.Values.AddRange(ids);
                if (!includenull)
                {
                    filter.AddCondition(cond);
                }
                else
                {
                    var orfilter = new FilterExpression(LogicalOperator.Or);
                    orfilter.AddCondition(attribute, Microsoft.Xrm.Sdk.Query.ConditionOperator.Null);
                    orfilter.AddCondition(cond);
                    filter.AddFilter(orfilter);
                }
                log.Log("Adding relation condition for {0} in {1} values in {2}.{3}", attribute, ids.Count, block, pkattribute);
            }
            log.EndSection();
        }
        private void ExportSolutionBlock(XmlNode xBlock)
        {
            log.StartSection("ExportSolutionBlock");

            if (xBlock.Name != "SolutionBlock")
            {
                throw new ArgumentOutOfRangeException("Type", xBlock.Name, "Invalid Block type");
            }
            string name = CintXML.GetAttribute(xBlock, "Name");

            log.Log("Block: {0}", name);
            string path = CintXML.GetAttribute(xBlock, "Path");
            string file = CintXML.GetAttribute(xBlock, "File");

            if (string.IsNullOrWhiteSpace(path) && !string.IsNullOrWhiteSpace(definitionpath))
            {
                path  = definitionpath;
                path += path.EndsWith("\\") ? "" : "\\";
            }
            if (string.IsNullOrWhiteSpace(file))
            {
                file = name;
            }
            XmlNode xExport = CintXML.FindChild(xBlock, "Export");

            if (xExport != null)
            {
                string type          = CintXML.GetAttribute(xExport, "Type");
                string setversion    = CintXML.GetAttribute(xExport, "SetVersion");
                bool   publish       = CintXML.GetBoolAttribute(xExport, "PublishBeforeExport", false);
                string targetversion = CintXML.GetAttribute(xExport, "TargetVersion");

                CintDynEntity cdSolution     = GetAndVerifySolutionForExport(name);
                var           currentversion = new Version(cdSolution.Property("version", "1.0.0.0"));

                SendLine("Solution: {0} {1}", name, currentversion);

                if (!string.IsNullOrWhiteSpace(setversion))
                {
                    SetNewSolutionVersion(setversion, cdSolution, currentversion);
                }

                if (publish)
                {
                    SendLine("Publishing customizations");
                    crmsvc.Execute(new PublishAllXmlRequest());
                }

                ExportSolutionRequest req = new ExportSolutionRequest()
                {
                    SolutionName = name
                };
#if Crm8
                if (!string.IsNullOrWhiteSpace(targetversion))
                {
                    req.TargetVersion = targetversion;
                }
#endif
                XmlNode xSettings = CintXML.FindChild(xExport, "Settings");
                if (xSettings != null)
                {
                    req.ExportAutoNumberingSettings          = CintXML.GetBoolAttribute(xSettings, "AutoNumbering", false);
                    req.ExportCalendarSettings               = CintXML.GetBoolAttribute(xSettings, "Calendar", false);
                    req.ExportCustomizationSettings          = CintXML.GetBoolAttribute(xSettings, "Customization", false);
                    req.ExportEmailTrackingSettings          = CintXML.GetBoolAttribute(xSettings, "EmailTracking", false);
                    req.ExportGeneralSettings                = CintXML.GetBoolAttribute(xSettings, "General", false);
                    req.ExportMarketingSettings              = CintXML.GetBoolAttribute(xSettings, "Marketing", false);
                    req.ExportOutlookSynchronizationSettings = CintXML.GetBoolAttribute(xSettings, "OutlookSync", false);
                    req.ExportRelationshipRoles              = CintXML.GetBoolAttribute(xSettings, "RelationshipRoles", false);
                    req.ExportIsvConfig = CintXML.GetBoolAttribute(xSettings, "IsvConfig", false);
                }

                if (type == "Managed" || type == "Both")
                {
                    string filename = path + file + "_managed.zip";
                    SendLine("Exporting solution to: {0}", filename);
                    req.Managed = true;
                    ExportSolutionResponse exportSolutionResponse = (ExportSolutionResponse)crmsvc.Execute(req);
                    byte[] exportXml = exportSolutionResponse.ExportSolutionFile;
                    File.WriteAllBytes(filename, exportXml);
                }
                if (type == "Unmanaged" || type == "Both")
                {
                    string filename = path + file + ".zip";
                    SendLine("Exporting solution to: {0}", filename);
                    req.Managed = false;
                    ExportSolutionResponse exportSolutionResponse = (ExportSolutionResponse)crmsvc.Execute(req);
                    byte[] exportXml = exportSolutionResponse.ExportSolutionFile;
                    File.WriteAllBytes(filename, exportXml);
                }
            }
            log.EndSection();
        }
        private Tuple <int, int, int, int, int, EntityReferenceCollection> ImportDataBlock(XmlNode xBlock, CintDynEntityCollection cEntities)
        {
            log.StartSection("ImportDataBlock");
            int created = 0;
            int updated = 0;
            int skipped = 0;
            int deleted = 0;
            int failed  = 0;
            EntityReferenceCollection references = new EntityReferenceCollection();

            string name = CintXML.GetAttribute(xBlock, "Name");

            log.Log("Block: {0}", name);
            SendStatus(name, null);
            SendLine();

            switch (xBlock.Name)
            {
            case "DataBlock":
                string  type    = CintXML.GetAttribute(xBlock, "Type");
                XmlNode xImport = CintXML.FindChild(xBlock, "Import");
                if (xImport != null)
                {
                    var includeid           = CintXML.GetBoolAttribute(xImport, "CreateWithId", false);
                    var save                = CintXML.GetAttribute(xImport, "Save");
                    var delete              = CintXML.GetAttribute(xImport, "Delete");
                    var updateinactive      = CintXML.GetBoolAttribute(xImport, "UpdateInactive", false);
                    var updateidentical     = CintXML.GetBoolAttribute(xImport, "UpdateIdentical", false);
                    var deprecatedoverwrite = CintXML.GetAttribute(xImport, "Overwrite");
                    if (!string.IsNullOrWhiteSpace(deprecatedoverwrite))
                    {
                        SendLine("DEPRECATED use of attribute Overwrite!");
                        bool overwrite = CintXML.GetBoolAttribute(xImport, "Overwrite", true);
                        save = overwrite ? "CreateUpdate" : "CreateOnly";
                    }
                    if (string.IsNullOrWhiteSpace(save))
                    {       // Default
                        save = "CreateUpdate";
                    }
                    if (string.IsNullOrWhiteSpace(delete))
                    {       // Default
                        delete = "None";
                    }
                    XmlNode xMatch           = CintXML.FindChild(xImport, "Match");
                    var     matchattributes  = GetMatchAttributes(xMatch);
                    var     updateattributes = !updateidentical?GetUpdateAttributes(cEntities) : new List <string>();

                    var preretrieveall = xMatch != null?CintXML.GetBoolAttribute(xMatch, "PreRetrieveAll", false) : false;

                    SendLine();
                    SendLine("Importing block {0} - {1} records ", name, cEntities.Count);

                    var i = 1;

                    if (delete == "All" && (matchattributes.Count == 0))
                    {       // All records shall be deleted, no match attribute defined, so just get all and delete all
                        string entity  = CintXML.GetAttribute(xBlock, "Entity");
                        var    qDelete = new QueryExpression(entity);
                        qDelete.ColumnSet.AddColumn(crmsvc.PrimaryAttribute(entity, log));
                        var deleterecords = CintDynEntity.RetrieveMultiple(crmsvc, qDelete, log);
                        SendLine("Deleting ALL {0} - {1} records", entity, deleterecords.Count);
                        foreach (var record in deleterecords)
                        {
                            SendLine("{0:000} Deleting existing: {1}", i, record);
                            try
                            {
                                record.Delete();
                                deleted++;
                            }
                            catch (FaultException <OrganizationServiceFault> ex)
                            {
                                if (ex.Message.ToUpperInvariant().Contains("DOES NOT EXIST"))
                                {       // This may happen through delayed cascade delete in CRM
                                    SendLine("      ...already deleted");
                                }
                                else
                                {
                                    throw;
                                }
                            }
                            i++;
                        }
                    }
                    int totalRecords = cEntities.Count;
                    i = 1;
                    CintDynEntityCollection cAllRecordsToMatch = null;
                    foreach (CintDynEntity cdEntity in cEntities)
                    {
                        string unique = cdEntity.Id.ToString();
                        SendStatus(-1, -1, totalRecords, i);
                        try
                        {
                            Guid oldid = cdEntity.Id;
                            Guid newid = Guid.Empty;

                            ReplaceGuids(cdEntity, includeid);
                            ReplaceUpdateInfo(cdEntity);
                            unique = GetEntityDisplayString(xMatch, cdEntity);
                            SendStatus(null, unique);

                            if (type == "Entity" || string.IsNullOrEmpty(type))
                            {
                                #region Entity

                                if (matchattributes.Count == 0)
                                {
                                    if (save == "Never" || save == "UpdateOnly")
                                    {
                                        skipped++;
                                        SendLine("{0:000} Not saving: {1}", i, unique);
                                    }
                                    else
                                    {
                                        if (!includeid)
                                        {
                                            cdEntity.Id = Guid.Empty;
                                        }
                                        if (SaveEntity(cdEntity, null, updateinactive, updateidentical, i, unique))
                                        {
                                            created++;
                                            newid = cdEntity.Id;
                                            references.Add(cdEntity.Entity.ToEntityReference());
                                        }
                                    }
                                }
                                else
                                {
                                    var matches = GetMatchingRecords(cdEntity, matchattributes, updateattributes, preretrieveall, ref cAllRecordsToMatch);
                                    if (delete == "All" || (matches.Count == 1 && delete == "Existing"))
                                    {
                                        foreach (CintDynEntity cdMatch in matches)
                                        {
                                            SendLine("{0:000} Deleting existing: {1}", i, unique);
                                            try
                                            {
                                                cdMatch.Delete();
                                                deleted++;
                                            }
                                            catch (FaultException <OrganizationServiceFault> ex)
                                            {
                                                if (ex.Message.ToUpperInvariant().Contains("DOES NOT EXIST"))
                                                {       // This may happen through cascade delete in CRM
                                                    SendLine("      ...already deleted");
                                                }
                                                else
                                                {
                                                    throw;
                                                }
                                            }
                                        }
                                        matches.Clear();
                                    }
                                    if (matches.Count == 0)
                                    {
                                        if (save == "Never" || save == "UpdateOnly")
                                        {
                                            skipped++;
                                            SendLine("{0:000} Not creating: {1}", i, unique);
                                        }
                                        else
                                        {
                                            if (!includeid)
                                            {
                                                cdEntity.Id = Guid.Empty;
                                            }
                                            if (SaveEntity(cdEntity, null, updateinactive, updateidentical, i, unique))
                                            {
                                                created++;
                                                newid = cdEntity.Id;
                                                references.Add(cdEntity.Entity.ToEntityReference());
                                            }
                                        }
                                    }
                                    else if (matches.Count == 1)
                                    {
                                        var match = matches[0];
                                        newid = match.Id;
                                        if (save == "CreateUpdate" || save == "UpdateOnly")
                                        {
                                            if (SaveEntity(cdEntity, match, updateinactive, updateidentical, i, unique))
                                            {
                                                updated++;
                                                references.Add(cdEntity.Entity.ToEntityReference());
                                            }
                                            else
                                            {
                                                skipped++;
                                            }
                                        }
                                        else
                                        {
                                            skipped++;
                                            SendLine("{0:000} Exists: {1}", i, unique);
                                        }
                                    }
                                    else
                                    {
                                        failed++;
                                        SendLine("Import object matches {0} records in target database!", matches.Count);
                                        SendLine(unique);
                                    }
                                }
                                if (!oldid.Equals(Guid.Empty) && !newid.Equals(Guid.Empty) && !oldid.Equals(newid) && !guidmap.ContainsKey(oldid))
                                {
                                    log.Log("Mapping IDs: {0} ==> {1}", oldid, newid);
                                    guidmap.Add(oldid, newid);
                                }

                                #endregion Entity
                            }
                            else if (type == "Intersect")
                            {
                                #region Intersect

                                if (cdEntity.Attributes.Count != 2)
                                {
                                    throw new ArgumentOutOfRangeException("Attributes", cdEntity.Attributes.Count, "Invalid Attribute count for intersect object");
                                }
                                string intersect = CintXML.GetAttribute(xBlock, "IntersectName");
                                if (string.IsNullOrEmpty(intersect))
                                {
                                    intersect = cdEntity.Name;
                                }

                                EntityReference ref1   = (EntityReference)cdEntity.Attributes.ElementAt(0).Value;
                                EntityReference ref2   = (EntityReference)cdEntity.Attributes.ElementAt(1).Value;
                                CintDynEntity   party1 = CintDynEntity.InitFromNameAndId(ref1.LogicalName, ref1.Id, crmsvc, log);
                                CintDynEntity   party2 = CintDynEntity.InitFromNameAndId(ref2.LogicalName, ref2.Id, crmsvc, log);
                                try
                                {
                                    party1.Associate(party2, intersect);
                                    created++;
                                    SendLine("{0} Associated: {1}", i.ToString().PadLeft(3, '0'), name);
                                }
                                catch (Exception ex)
                                {
                                    if (ex.Message.Contains("duplicate"))
                                    {
                                        SendLine("{0} Association exists: {1}", i.ToString().PadLeft(3, '0'), name);
                                        skipped++;
                                    }
                                    else
                                    {
                                        throw;
                                    }
                                }

                                #endregion Intersect
                            }
                        }
                        catch (Exception ex)
                        {
                            failed++;
                            SendLine("\n*** Error record: {0} ***\n{1}", unique, ex.Message);
                            log.Log(ex);
                            if (stoponerror)
                            {
                                throw;
                            }
                        }
                        i++;
                    }

                    SendLine("Created: {0} Updated: {1} Skipped: {2} Deleted: {3} Failed: {4}", created, updated, skipped, deleted, failed);
                }
                break;

            default:
                throw new ArgumentOutOfRangeException("Type", xBlock.Name, "Invalid Block type");
            }
            log.EndSection();
            return(new Tuple <int, int, int, int, int, EntityReferenceCollection>(created, updated, skipped, deleted, failed, references));
        }
        private ItemImportResult ImportSolutionBlock(XmlNode xBlock)
        {
            log.StartSection("ImportSolutionBlock");
            var importResult = ItemImportResult.None;

            if (xBlock.Name != "SolutionBlock")
            {
                throw new ArgumentOutOfRangeException("Type", xBlock.Name, "Invalid Block type");
            }
            XmlNode xImport = CintXML.FindChild(xBlock, "Import");

            if (xImport != null)
            {
                string name = CintXML.GetAttribute(xBlock, "Name");
                log.Log("Block: {0}", name);
                SendStatus(name, null);
                string type = CintXML.GetAttribute(xImport, "Type");
                SendLine();
                SendLine("Importing solution: {0}", name);

                string filename = GetSolutionFilename(xBlock, name, type);
                var    version  = ExtractVersionFromSolutionZip(filename);
                try
                {
                    ValidatePreReqs(xImport, version);
                    SolutionImportConditions ImportCondition = CheckIfImportRequired(xImport, name, version);
                    if (ImportCondition != SolutionImportConditions.Skip)
                    {
                        if (DoImportSolution(xImport, filename, version))
                        {
                            if (ImportCondition == SolutionImportConditions.Create)
                            {
                                importResult = ItemImportResult.Created;
                            }
                            else
                            {
                                importResult = ItemImportResult.Updated;
                            }
                        }
                        else
                        {
                            importResult = ItemImportResult.Failed;
                            log.Log("Failed during import");
                        }
                        bool publish = CintXML.GetBoolAttribute(xImport, "PublishAll", false);
                        if (publish)
                        {
                            SendLine("Publishing customizations");
                            crmsvc.Execute(new PublishAllXmlRequest());
                        }
                    }
                    else
                    {
                        importResult = ItemImportResult.Skipped;
                        log.Log("Skipped due to import condition");
                    }
                }
                catch (Exception ex)
                {
                    log.Log(ex);
                    importResult = ItemImportResult.Failed;
                    if (stoponerror)
                    {
                        throw;
                    }
                }
            }
            log.EndSection();
            return(importResult);
        }