Example #1
0
        private bool ReadAndLogSolutionImportJobStatus(Guid jobid)
        {
            log.StartSection("ReadAndLogSolutionImportJobStatus " + jobid);
            var success = false;
            var job     = CintDynEntity.Retrieve("importjob", jobid, new ColumnSet("startedon", "completedon", "progress", "data"), crmsvc, log);

            if (job != null)
            {
                var name     = "?";
                var result   = "?";
                var err      = "";
                var start    = job.Property("startedon", DateTime.MinValue);
                var complete = job.Property("completedon", DateTime.MinValue);
                var time     = complete != null && start != null?complete.Subtract(start) : new TimeSpan();

                var prog = job.Property <double>("progress", 0);
                if (job.Contains("data", true))
                {
                    var doc  = new XmlDocument();
                    var data = job.Property("data", "");
                    log.Log("Job data length: {0}", data.Length);
                    if (!string.IsNullOrWhiteSpace(data))
                    {
                        doc.LoadXml(data);
                        var namenode = doc.SelectSingleNode("//solutionManifest/UniqueName");
                        if (namenode != null)
                        {
                            name = namenode.InnerText;
                        }
                        var resultnode = doc.SelectSingleNode("//solutionManifest/result/@result");
                        if (resultnode != null)
                        {
                            result = resultnode.Value;
                        }
                        var errnode = doc.SelectSingleNode("//solutionManifest/result/@errortext");
                        if (errnode != null)
                        {
                            err = errnode.Value;
                        }
                    }
                }
                if (prog >= 100 && result == "success")
                {
                    SendLine("Solution {0} imported in {1}", name, time);
                    log.Log("Result: {0}\nError:  {1}\nTime:   {2}", result, err, time);
                    success = true;
                }
                else
                {
                    SendLine("Solution: {0}", name);
                    SendLine("Result:   {0}", result);
                    SendLine("Error:    {0}", err);
                    SendLine("Progress: {0}", prog);
                    SendLine("Time:     {0}", time);
                }
            }
            log.Log("Returning: {0}", success);
            log.EndSection();
            return(success);
        }
        private CintDynEntityCollection GetMatchingRecords(CintDynEntity cdEntity, List <string> matchattributes, List <string> updateattributes, bool preretrieveall, ref CintDynEntityCollection cAllRecordsToMatch)
        {
            log.StartSection(MethodBase.GetCurrentMethod().Name);
            CintDynEntityCollection matches = null;
            var allattributes = new List <string>();

            allattributes.Add(cdEntity.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(allattributes, cdEntity);
                }
                matches = GetMatchingRecordsFromPreRetrieved(matchattributes, cdEntity, cAllRecordsToMatch);
            }
            else
            {
                QueryExpression qMatch = new QueryExpression(cdEntity.Name);
                // 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
                qMatch.ColumnSet = new ColumnSet(allattributes.ToArray());

                foreach (var matchattr in matchattributes)
                {
                    object value = null;
                    if (cdEntity.Entity.Contains(matchattr))
                    {
                        value = CintEntity.AttributeToBaseType(cdEntity.Entity[matchattr]);
                    }
                    else if (matchattr == cdEntity.PrimaryIdAttribute)
                    {
                        value = cdEntity.Id;
                    }
                    if (value != null)
                    {
                        CintQryExp.AppendCondition(qMatch.Criteria, LogicalOperator.And, matchattr, Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal, value);
                    }
                    else
                    {
                        CintQryExp.AppendCondition(qMatch.Criteria, LogicalOperator.And, matchattr, Microsoft.Xrm.Sdk.Query.ConditionOperator.Null, null);
                    }
                }
#if DEBUG
                log.Log("Finding matches for {0}:\n{1}", cdEntity, CintQryExp.ConvertToFetchXml(qMatch, crmsvc));
#endif
                matches = CintDynEntity.RetrieveMultiple(crmsvc, qMatch, log);
            }
            log.EndSection();
            return(matches);
        }
Example #3
0
        private CintDynEntityCollection GetExistingSolutions()
        {
            CintDynEntityCollection cSolutions = CintDynEntity.RetrieveMultiple(crmsvc, "solution",
                                                                                new string[] { "isvisible" },
                                                                                new object[] { true },
                                                                                new ColumnSet("solutionid", "uniquename", "friendlyname", "version", "ismanaged"), log);

            return(cSolutions);
        }
 /// <summary>
 /// Creates the provided web resource
 /// </summary>
 /// <param name="webResource">Web resource to create</param>
 internal static Guid CreateWebResource(this CintContainer container, CintDynEntity webResource)
 {
     try
     {
         return(webResource.Create());
     }
     catch (Exception error)
     {
         throw new Exception("Error while creating web resource: " + error.Message);
     }
 }
 /// <summary>
 /// Deletes the provided web resource
 /// </summary>
 /// <param name="webResource">Web resource to delete</param>
 internal static void DeleteWebResource(this CintContainer container, CintDynEntity webResource)
 {
     try
     {
         webResource.Delete();
     }
     catch (Exception error)
     {
         throw new Exception("Error while deleting web resource: " + error.Message);
     }
 }
 /// <summary>
 /// Retrieves a specific web resource from its unique identifier
 /// </summary>
 /// <param name="webresourceId">Web resource unique identifier</param>
 /// <returns>Web resource</returns>
 internal static CintDynEntity RetrieveWebResource(this CintContainer container, Guid webresourceId)
 {
     try
     {
         return(CintDynEntity.Retrieve(container, "webresource", webresourceId, new ColumnSet(true)));
     }
     catch (Exception error)
     {
         throw new Exception("Error while retrieving web resource: " + error.Message);
     }
 }
Example #7
0
        private void UpdateAssembly(CintDynEntity plugin)
        {
            WriteVerbose("Reading assembly file " + AssemblyFile);
            var file = this.ReadFile(AssemblyFile);

            WriteVerbose("Adding Base64String to entity");
            var updateplugin = plugin.Clone(true);

            updateplugin.AddProperty("version", fileversion.ToString());
            updateplugin.AddProperty("content", Convert.ToBase64String(file));
            WriteObject("Saving updated assembly record");
            updateplugin.Save();
        }
        private CintDynEntityCollection GetAllRecordsForMatching(List <string> allattributes, CintDynEntity cdEntity)
        {
            log.StartSection(MethodBase.GetCurrentMethod().Name);
            QueryExpression qMatch = new QueryExpression(cdEntity.Name);

            qMatch.ColumnSet = new ColumnSet(allattributes.ToArray());
#if DEBUG
            log.Log("Retrieving all records for {0}:\n{1}", cdEntity.Name, CintQryExp.ConvertToFetchXml(qMatch, crmsvc));
#endif
            CintDynEntityCollection matches = CintDynEntity.RetrieveMultiple(crmsvc, qMatch, log);
            SendLine("Pre-retrieved {0} records for matching", matches.Count);
            log.EndSection();
            return(matches);
        }
Example #9
0
        private CintDynEntity GetAssembly(CintContainer container)
        {
            WriteObject($"Reading assembly file {AssemblyFile}");
            var file = ReadFile(AssemblyFile);

            WriteVerbose("Loading assembly file");
            var assembly = Assembly.Load(file);

            var chunks = assembly.FullName.Split(new string[] { ", ", "Version=", "Culture=", "PublicKeyToken=" }, StringSplitOptions.RemoveEmptyEntries);

            filename    = chunks[0];
            fileversion = new Version(chunks[1]);
            fileculture = chunks[2];
            filetoken   = chunks[3];
            WriteObject($"Loaded assembly {filename} {fileversion}");
            WriteVerbose("Culture: " + fileculture);
            WriteVerbose("Token  : " + filetoken);

            var query = new QueryExpression("pluginassembly");

            query.ColumnSet.AddColumns("name", "version", "ismanaged");
            query.Criteria.AddCondition("name", Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal, filename);
            query.Criteria.AddCondition("version", Microsoft.Xrm.Sdk.Query.ConditionOperator.Like, fileversion.ToString(2) + "%");
            query.Criteria.AddCondition("culture", Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal, fileculture);
            query.Criteria.AddCondition("publickeytoken", Microsoft.Xrm.Sdk.Query.ConditionOperator.Equal, filetoken);

            var plugin = CintDynEntity.RetrieveMultiple(container, query).FirstOrDefault();

            if (plugin != null)
            {
                WriteObject($"Found plugin: {plugin} {plugin.Property("version", "?")}");
                if (plugin.Property("ismanaged", false))
                {
                    if (!UpdateManaged)
                    {
                        throw new ArgumentOutOfRangeException("AssemblyFile", AssemblyFile, "Assembly is managed in target CRM. Use parameter UpdateManaged to allow this.");
                    }
                    else
                    {
                        WriteWarning("Updating managed assembly");
                    }
                }
                return(plugin);
            }
            else
            {
                throw new ArgumentOutOfRangeException("AssemblyFile", AssemblyFile, "Assembly does not appear to be registered in CRM");
            }
        }
        private CintDynEntity GetAndVerifySolutionForExport(string name)
        {
            var cSolutions = CintDynEntity.RetrieveMultiple(crmsvc, "solution",
                                                            new string[] { "isvisible", "uniquename" },
                                                            new object[] { true, name },
                                                            new ColumnSet("solutionid", "friendlyname", "version", "ismanaged"), log);

            if (cSolutions.Count == 0)
            {
                throw new ArgumentOutOfRangeException("SolutionUniqueName", name, "Cannot find solution");
            }
            if (cSolutions.Count > 1)
            {
                throw new ArgumentOutOfRangeException("SolutionUniqueName", name, "Found " + cSolutions.Count.ToString() + " matching solutions");
            }
            var cdSolution = cSolutions[0];

            return(cdSolution);
        }
Example #11
0
        private static string GetEntityDisplayString(DataBlockImportMatch match, CintDynEntity cdEntity)
        {
            var unique = new List <string>();

            if (match != null && match.Attribute.Length > 0)
            {
                foreach (var attribute in match.Attribute)
                {
                    var matchdisplay = attribute.Display;
                    if (string.IsNullOrEmpty(matchdisplay))
                    {
                        matchdisplay = attribute.Name;
                    }
                    var matchvalue = "<null>";
                    if (cdEntity.Contains(matchdisplay, true))
                    {
                        if (cdEntity.Entity[matchdisplay] is EntityReference)
                        {   // Don't use PropertyAsString, that would perform GetRelated that we don't want due to performance
                            var entref = cdEntity.Property <EntityReference>(matchdisplay, null);
                            if (!string.IsNullOrEmpty(entref.Name))
                            {
                                matchvalue = entref.Name;
                            }
                            else
                            {
                                matchvalue = entref.LogicalName + ":" + entref.Id.ToString();
                            }
                        }
                        else
                        {
                            matchvalue = cdEntity.PropertyAsString(matchdisplay, "", false, false, true);
                        }
                    }
                    unique.Add(matchvalue);
                }
            }
            if (unique.Count == 0)
            {
                unique.Add(cdEntity.Id.ToString());
            }
            return(string.Join(", ", unique));
        }
        private static string GetEntityDisplayString(XmlNode xMatch, CintDynEntity cdEntity)
        {
            var unique = new List <string>();

            if (xMatch != null && xMatch.ChildNodes.Count > 0)
            {
                foreach (XmlNode xMatchAttr in xMatch.ChildNodes)
                {
                    string matchdisplay = CintXML.GetAttribute(xMatchAttr, "Display");
                    if (string.IsNullOrEmpty(matchdisplay))
                    {
                        matchdisplay = CintXML.GetAttribute(xMatchAttr, "Name");
                    }
                    var matchvalue = "<null>";
                    if (cdEntity.Contains(matchdisplay, true))
                    {
                        if (cdEntity.Entity[matchdisplay] is EntityReference)
                        {   // Don't use PropertyAsString, that would perform GetRelated that we don't want due to performance
                            var entref = cdEntity.Property <EntityReference>(matchdisplay, null);
                            if (!string.IsNullOrEmpty(entref.Name))
                            {
                                matchvalue = entref.Name;
                            }
                            else
                            {
                                matchvalue = entref.LogicalName + ":" + entref.Id.ToString();
                            }
                        }
                        else
                        {
                            matchvalue = cdEntity.PropertyAsString(matchdisplay, "", false, false, true);
                        }
                    }
                    unique.Add(matchvalue);
                }
            }
            if (unique.Count == 0)
            {
                unique.Add(cdEntity.Id.ToString());
            }
            return(string.Join(", ", unique));
        }
        /// <summary>
        /// Updates the provided web resource
        /// </summary>
        /// <param name="script">Web resource to update</param>
        internal static void UpdateWebResource(this CintContainer container, CintDynEntity wr)
        {
            try
            {
                var script = wr;

                if (!script.Contains("webresourceid"))
                {
                    var existingEntity = container.RetrieveWebResource(script.Property("name", ""));

                    if (existingEntity == null)
                    {
                        script.Id = container.CreateWebResource(script);
                    }
                    else
                    {
                        script.Id = existingEntity.Id;

                        if (!script.Contains("displayname") && existingEntity.Contains("displayname"))
                        {
                            script.AddProperty("displayname", existingEntity.Property("displayname", ""));
                        }

                        if (!script.Contains("description") && existingEntity.Contains("description"))
                        {
                            script.AddProperty("description", existingEntity.Property("description", ""));
                        }

                        script.Save();
                    }
                }
                else
                {
                    script.Save();
                }
            }
            catch (Exception error)
            {
                throw new Exception("Error while updating web resource: " + error.Message);
            }
        }
        private static void ReplaceUpdateInfo(CintDynEntity cdEntity)
        {
            List <string> removeAttr = new List <string>();
            List <KeyValuePair <string, object> > newAttr = new List <KeyValuePair <string, object> >();

            foreach (KeyValuePair <string, object> attr in cdEntity.Attributes)
            {
                if (attr.Key == "createdby")
                {
                    if (!cdEntity.Attributes.Contains("createdonbehalfby"))
                    {
                        newAttr.Add(new KeyValuePair <string, object>("createdonbehalfby", attr.Value));
                    }
                    removeAttr.Add("createdby");
                }
                else if (attr.Key == "modifiedby")
                {
                    if (!cdEntity.Attributes.Contains("modifiedonbehalfby"))
                    {
                        newAttr.Add(new KeyValuePair <string, object>("modifiedonbehalfby", attr.Value));
                    }
                    removeAttr.Add("modifiedby");
                }
                else if (attr.Key == "createdon")
                {
                    if (!cdEntity.Attributes.Contains("overriddencreatedon"))
                    {
                        newAttr.Add(new KeyValuePair <string, object>("overriddencreatedon", attr.Value));
                    }
                    removeAttr.Add("createdon");
                }
            }
            foreach (string key in removeAttr)
            {
                cdEntity.Attributes.Remove(key);
            }
            if (newAttr.Count > 0)
            {
                cdEntity.Attributes.AddRange(newAttr);
            }
        }
 private void ReplaceGuids(CintDynEntity cdEntity, bool includeid)
 {
     foreach (KeyValuePair <string, object> prop in cdEntity.Attributes)
     {
         if (prop.Value is Guid && guidmap.ContainsKey((Guid)prop.Value))
         {
             if (includeid)
             {
                 throw new NotImplementedException("Cannot handle replacement of Guid type attributes");
             }
             else
             {
                 log.Log("No action, we don't care about the guid of the object");
             }
         }
         if (prop.Value is EntityReference && guidmap.ContainsKey(((EntityReference)prop.Value).Id))
         {
             ((EntityReference)prop.Value).Id = guidmap[((EntityReference)prop.Value).Id];
         }
     }
 }
 private void GetSolutions()
 {
     if (Service == null)
     {
         return;
     }
     if (working)
     {
         return;
     }
     working = true;
     WorkAsync(new WorkAsyncInfo("Loading solutions",
                                 (eventargs) =>
     {
         var svc = new CrmServiceProxy(Service);
         var log = new PluginLogger("ShuffleBuilder", true, "");
         try
         {
             solutionsUnmanaged = CintDynEntity.RetrieveMultiple(svc, "solution",
                                                                 new string[] { "isvisible", "ismanaged" },
                                                                 new object[] { true, false },
                                                                 new ColumnSet("solutionid", "uniquename", "friendlyname", "version"), log);
         }
         finally
         {
             log.CloseLog();
         }
     })
     {
         PostWorkCallBack =
             (completedargs) =>
         {
             if (completedargs.Error != null)
             {
                 MessageBox.Show(completedargs.Error.Message);
             }
             working = false;
         }
     });
 }
        /// <summary>
        /// Retrieves a specific web resource from its unique name
        /// </summary>
        /// <param name="name">Web resource unique name</param>
        /// <returns>Web resource</returns>
        internal static CintDynEntity RetrieveWebResource(this CintContainer container, string name)
        {
            try
            {
                var qba = new QueryByAttribute("webresource");
                qba.Attributes.Add("name");
                qba.Values.Add(name);
                qba.ColumnSet = new ColumnSet(true);

                var collection = CintDynEntity.RetrieveMultiple(container, qba);

                if (collection.Count > 1)
                {
                    throw new Exception(string.Format("there are more than one web resource with name '{0}'", name));
                }

                return(collection.FirstOrDefault());
            }
            catch (Exception error)
            {
                throw new Exception("Error while retrieving web resource: " + error.Message);
            }
        }
        private static bool EntityAttributesEqual(List <string> matchattributes, CintDynEntity entity1, CintDynEntity entity2)
        {
            var match = true;

            foreach (var attr in matchattributes)
            {
                var srcvalue = "";
                if (attr == entity1.PrimaryIdAttribute)
                {
                    srcvalue = entity1.Id.ToString();
                }
                else
                {
                    srcvalue = entity1.PropertyAsBaseType(attr, "<null>", false, false, true).ToString();
                }
                var trgvalue = entity2.PropertyAsBaseType(attr, "<null>", false, false, true).ToString();
                if (srcvalue != trgvalue)
                {
                    match = false;
                    break;
                }
            }
            return(match);
        }
        private void SetNewSolutionVersion(string setversion, CintDynEntity cdSolution, Version currentversion)
        {
            Version newversion;

            if (setversion.Equals("IncrementAll", StringComparison.OrdinalIgnoreCase))
            {
                newversion = new Version("1.0.0.0");
                foreach (var existingversion in ExistingSolutionVersions.Values)
                {
                    if (existingversion > newversion)
                    {
                        newversion = existingversion;
                    }
                }
                newversion = IncrementVersion(newversion);
            }
            else if (setversion.Equals("Increment", StringComparison.OrdinalIgnoreCase))
            {
                newversion = IncrementVersion(currentversion);
            }
            else if (setversion.Equals("Current", StringComparison.OrdinalIgnoreCase))
            {
                newversion = currentversion;
            }
            else
            {
                newversion = new Version(setversion);
            }
            if (!currentversion.Equals(newversion))
            {
                SendLine("Setting version: {0}", newversion);
                var cdSolUpd = cdSolution.Clone(true);
                cdSolUpd.AddProperty("version", newversion.ToString());
                cdSolUpd.Save();
            }
        }
Example #20
0
        private Tuple <int, int, int, int, int, EntityReferenceCollection> ImportDataBlock(DataBlock block, CintDynEntityCollection cEntities)
        {
            log.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;

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

            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("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();
                SendLine("Importing block {0} - {1} records ", name, cEntities.Count);

                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(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++;
                    }
                }
                var totalRecords = cEntities.Count;
                i = 1;
                CintDynEntityCollection cAllRecordsToMatch = null;
                foreach (var cdEntity in cEntities)
                {
                    var unique = cdEntity.Id.ToString();
                    SendStatus(-1, -1, totalRecords, i);
                    try
                    {
                        var oldid = cdEntity.Id;
                        var newid = Guid.Empty;

                        ReplaceGuids(cdEntity, includeid);
                        ReplaceUpdateInfo(cdEntity);
                        unique = GetEntityDisplayString(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("{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 == DeleteTypes.All || (matches.Count == 1 && delete == DeleteTypes.Existing))
                                {
                                    foreach (var 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 == SaveTypes.Never || save == SaveTypes.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 == SaveTypes.CreateUpdate || save == SaveTypes.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 (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.Name;
                            }

                            var ref1   = (EntityReference)cdEntity.Attributes.ElementAt(0).Value;
                            var ref2   = (EntityReference)cdEntity.Attributes.ElementAt(1).Value;
                            var party1 = CintDynEntity.InitFromNameAndId(ref1.LogicalName, ref1.Id, crmsvc, log);
                            var 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);
            }
            log.EndSection();
            return(new Tuple <int, int, int, int, int, EntityReferenceCollection>(created, updated, skipped, deleted, failed, references));
        }
        private CintDynEntityCollection ExportDataBlock(ShuffleBlocks blocks, DataBlock block)
        {
            log.StartSection("ExportDataBlock");
            log.Log("Block: {0}", block.Name);
            CintDynEntityCollection 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;
                        log.Log("Adding column: {0}", attr);
                        lAttributes.Add(attr.Replace("*", "%"));
                        if (attr.Contains("*"))
                        {
                            allcolumns = true;
                            log.Log("Found wildcard");
                        }
                        else
                        {
                            if (attribute.IncludeNull)
                            {
                                lNullAttributes.Add(attr);
                            }
                        }
                    }
                }
                else
                {
                    allcolumns = true;
                    lAttributes.Add("*");
                    log.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))
                {
                    log.StartSection("Export entity using FetchXML");
#if DEBUG
                    log.Log("FetchXML:\n{0}", fetchxml);
#endif
                    cExportEntities = CintDynEntity.RetrieveMultiple(crmsvc, new FetchExpression(fetchxml), log);
                    log.EndSection();
                }
                else if (!block.TypeSpecified || block.Type == EntityTypes.Entity)
                {
                    #region QueryExpression Entity

                    log.StartSection("Export entity " + block.Entity);
                    var qExport = new QueryExpression(block.Entity);
                    if (block.Export.ActiveOnly)
                    {
                        CintQryExp.AppendConditionActive(qExport.Criteria);
                    }

                    if (block.Relation != null)
                    {
                        foreach (var relation in block.Relation)
                        {
                            AddRelationFilter(blocks, block.Entity, relation, qExport.Criteria, log);
                        }
                    }
                    foreach (var filter in block.Export.Items.Where(i => i is DataBlockExportFilter).Cast <DataBlockExportFilter>())
                    {
                        AddFilter(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
                    log.Log("Converting to FetchXML");
                    try
                    {
                        var fetch = CintQryExp.ConvertToFetchXml(qExport, crmsvc);
                        log.Log("Exporting {0}:\n{1}", block.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", block.Name, cExportEntities.Count);
                    log.EndSection();

                    #endregion QueryExpression Entity
                }
                else if (block.Type == EntityTypes.Intersect)
                {
                    #region FetchXML Intersect

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

                    if (block.Relation != null)
                    {
                        foreach (var relation in block.Relation)
                        {
                            AddRelationFilter(blocks, relation, 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}", block.Entity, fetch);
#endif
                    var qExport = new FetchExpression(fetch);
                    cExportEntities = CintDynEntity.RetrieveMultiple(crmsvc, qExport, log);
                    foreach (var cde in cExportEntities)
                    {
                        var newattributes = new List <KeyValuePair <string, object> >();
                        foreach (var attr in cde.Attributes)
                        {
                            if (attr.Value is Guid)
                            {
                                var attrname      = attr.Key;
                                var 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);
        }
Example #22
0
 public static void PublishDuplicateRule(this CintDynEntity duplicateRule) => duplicateRule.Container.Service.Execute(new PublishDuplicateRuleRequest {
     DuplicateRuleId = duplicateRule.Id
 });
        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 CintDynEntityCollection GetMatchingRecordsFromPreRetrieved(List <string> matchattributes, CintDynEntity cdEntity, CintDynEntityCollection cAllRecordsToMatch)
        {
            log.StartSection(MethodBase.GetCurrentMethod().Name);
            log.Log("Searching matches for: {0} {1}", cdEntity.Id, cdEntity);
            var result = new CintDynEntityCollection();

            foreach (var cdRecord in cAllRecordsToMatch)
            {
                if (EntityAttributesEqual(matchattributes, cdEntity, cdRecord))
                {
                    result.Add(cdRecord);
                    log.Log("Found match: {0} {1}", cdRecord.Id, cdRecord);
                }
            }
            log.Log("Returned matches: {0}", result.Count);
            log.EndSection();
            return(result);
        }
        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();
        }
        /// <summary>
        /// Retrieves all web resources that are customizable
        /// </summary>
        /// <returns>List of web resources</returns>
        internal static CintDynEntityCollection RetrieveWebResources(this CintContainer container, Guid solutionId, List <int> types, bool hideMicrosoftWebresources)
        {
            try
            {
                if (solutionId == Guid.Empty)
                {
                    var qe = new QueryExpression("webresource")
                    {
                        ColumnSet = new ColumnSet(true),
                        Criteria  = new FilterExpression
                        {
                            Filters =
                            {
                                new FilterExpression
                                {
                                    FilterOperator = LogicalOperator.And,
                                    Conditions     =
                                    {
                                        new ConditionExpression("ishidden", ConditionOperator.Equal, false),
                                    }
                                },
                                new FilterExpression
                                {
                                    FilterOperator = LogicalOperator.Or,
                                    Conditions     =
                                    {
                                        new ConditionExpression("ismanaged",      ConditionOperator.Equal, false),
                                        new ConditionExpression("iscustomizable", ConditionOperator.Equal, true),
                                    }
                                }
                            }
                        },
                        Orders = { new OrderExpression("name", OrderType.Ascending) }
                    };

                    if (hideMicrosoftWebresources)
                    {
                        qe.Criteria.Filters.First().Conditions.AddRange(
                            new ConditionExpression("name", ConditionOperator.DoesNotBeginWith, "cc_MscrmControls"),
                            new ConditionExpression("name", ConditionOperator.DoesNotBeginWith, "msdyn_")
                            );
                    }

                    if (types.Count != 0)
                    {
                        qe.Criteria.Filters.First().Conditions.Add(new ConditionExpression("webresourcetype", ConditionOperator.In, types.ToArray()));
                    }

                    return(CintDynEntity.RetrieveMultiple(container, qe));
                }
                else
                {
                    var qba = new QueryByAttribute("solutioncomponent")
                    {
                        ColumnSet = new ColumnSet(true)
                    };
                    qba.Attributes.AddRange(new[] { "solutionid", "componenttype" });
                    qba.Values.AddRange(new object[] { solutionId, 61 });

                    var components = CintDynEntity.RetrieveMultiple(container, qba);

                    var list =
                        components.Select(component => component.Property("objectid", Guid.Empty).ToString("B"))
                        .ToList();

                    if (list.Count > 0)
                    {
                        var qe = new QueryExpression("webresource")
                        {
                            ColumnSet = new ColumnSet(true),
                            Criteria  = new FilterExpression
                            {
                                Filters =
                                {
                                    new FilterExpression
                                    {
                                        FilterOperator = LogicalOperator.And,
                                        Conditions     =
                                        {
                                            new ConditionExpression("ishidden",      ConditionOperator.Equal, false),
                                            new ConditionExpression("webresourceid", ConditionOperator.In,    list.ToArray()),
                                        }
                                    },
                                    new FilterExpression
                                    {
                                        FilterOperator = LogicalOperator.Or,
                                        Conditions     =
                                        {
                                            new ConditionExpression("ismanaged",      ConditionOperator.Equal, false),
                                            new ConditionExpression("iscustomizable", ConditionOperator.Equal, true),
                                        }
                                    }
                                }
                            },
                            Orders = { new OrderExpression("name", OrderType.Ascending) }
                        };

                        if (types.Count != 0)
                        {
                            qe.Criteria.Filters.First().Conditions.Add(new ConditionExpression("webresourcetype", ConditionOperator.In, types.ToArray()));
                        }

                        return(CintDynEntity.RetrieveMultiple(container, qe));
                    }

                    return(new CintDynEntityCollection());
                }
            }
            catch (Exception error)
            {
                throw new Exception("Error while retrieving web resources: " + error.Message);
            }
        }
Example #27
0
        private bool DoImportSolutionAsync(ImportSolutionRequest impSolReq, ref Exception ex)
        {
            log.StartSection(MethodBase.GetCurrentMethod().Name);
            // Code cred to Wael Hamze
            // http://waelhamze.com/2013/11/17/asynchronous-solution-import-dynamics-crm-2013/
            var result       = false;
            var asyncRequest = new ExecuteAsyncRequest()
            {
                Request = impSolReq
            };
            var asyncResponse = crmsvc.Execute(asyncRequest) as ExecuteAsyncResponse;
            var asyncJobId    = asyncResponse.AsyncJobId;
            var end           = DateTime.MaxValue;
            var importStatus  = -1;
            var progress      = 0;
            var statustext    = "Submitting job";

            SendLineUpdate("Import status: {0}", statustext);
            while (end >= DateTime.Now)
            {
                CintDynEntity cdAsyncOperation = null;
                try
                {
                    cdAsyncOperation = CintDynEntity.Retrieve(SystemJob.EntityName, asyncJobId,
                                                              new ColumnSet(SystemJob.PrimaryKey, SystemJob.Status, SystemJob.StatusReason, SystemJob.Message, SystemJob.Friendlymessage), crmsvc, log);
                }
                catch (Exception asyncex)
                {
                    cdAsyncOperation = null;
                    log.Log(asyncex);
                    log.EndSection();   // Ending section started by Retrieve above to prevent indentation inflation
                }
                if (cdAsyncOperation != null)
                {
                    statustext = cdAsyncOperation.PropertyAsString(SystemJob.StatusReason, "?", false, false);
                    var newStatus = cdAsyncOperation.Property(SystemJob.StatusReason, new OptionSetValue()).Value;
                    if (newStatus != importStatus)
                    {
                        importStatus = newStatus;
                        if (end.Equals(DateTime.MaxValue) && importStatus != (int)SystemJob.StatusReason_OptionSet.Waiting)
                        {
                            end = timeout > 0 ? DateTime.Now.AddMinutes(timeout) : DateTime.Now.AddMinutes(2);
                            SendLineUpdate("Import job picked up at {0}", DateTime.Now);
                            log.Log("Timout until: {0}", end.ToString("HH:mm:ss.fff"));
                            SendLine("Import status: {0}", statustext);
                        }
                        SendLineUpdate("Import status: {0}", statustext);
                        log.Log("Import message:\n{0}", cdAsyncOperation.Property(SystemJob.Message, "<none>"));
                        if (importStatus == (int)SystemJob.StatusReason_OptionSet.Succeeded)
                        {   // Succeeded
                            result = true;
                            break;
                        }
                        else if (importStatus == (int)SystemJob.StatusReason_OptionSet.Pausing ||
                                 importStatus == (int)SystemJob.StatusReason_OptionSet.Canceling ||
                                 importStatus == (int)SystemJob.StatusReason_OptionSet.Failed ||
                                 importStatus == (int)SystemJob.StatusReason_OptionSet.Canceled)
                        {   // Error statuses
                            var friendlymessage = cdAsyncOperation.Property(SystemJob.Friendlymessage, "");
                            SendLine("Message: {0}", friendlymessage);
                            if (friendlymessage == "Access is denied.")
                            {
                                SendLine("When importing to onprem environment, the async service user must be granted read/write permission to folder:");
                                SendLine("  C:\\Program Files\\Microsoft Dynamics CRM\\CustomizationImport");
                            }
                            else
                            {
                                var message = cdAsyncOperation.Property(SystemJob.Message, "<none>");
                                message = ExtractErrorMessage(message);
                                if (!string.IsNullOrWhiteSpace(message) && !message.Equals(friendlymessage, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    SendLine("Detailed message: \n{0}", message);
                                }
                                else
                                {
                                    SendLine("See log file for technical details.");
                                }
                            }
                            ex = new Exception(string.Format("Solution Import Failed: {0} - {1}",
                                                             cdAsyncOperation.PropertyAsString(SystemJob.Status, "?", false, false),
                                                             cdAsyncOperation.PropertyAsString(SystemJob.StatusReason, "?", false, false)));
                            break;
                        }
                    }
                }
                System.Threading.Thread.Sleep(1000);
                if (importStatus == 20)
                {   // In progress, read percent
                    try
                    {
                        var job = CintDynEntity.Retrieve(ImportJob.EntityName, impSolReq.ImportJobId, new ColumnSet(ImportJob.Progress), crmsvc, log);
                        if (job != null)
                        {
                            var newProgress = Convert.ToInt32(Math.Round(job.Property(ImportJob.Progress, 0D)));
                            if (newProgress > progress)
                            {
                                progress = newProgress;
                                SendStatus(-1, -1, 100, progress);
                                SendLineUpdate("Import status: {0} - {1}%", statustext, progress);
                            }
                        }
                    }
                    catch (Exception jobex)
                    {   // We probably tried before the job was created
                        if (jobex.Message.ToUpperInvariant().Contains("DOES NOT EXIST"))
                        {
                            log.Log("Importjob not created yet or already deleted");
                        }
                        else
                        {
                            log.Log(jobex);
                        }
                        log.EndSection();   // Ending section started by Retrieve above to prevent indentation inflation
                    }
                }
            }
            if (end < DateTime.Now)
            {
                SendLine("Import timed out.");
            }
            SendStatus(-1, -1, 100, 0);
            log.EndSection();
            return(result);
        }
        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 bool SaveEntity(CintDynEntity cdNewEntity, CintDynEntity cdMatchEntity, bool updateInactiveRecord, bool updateIdentical, int pos, string identifier)
        {
            log.StartSection("SaveEntity " + pos.ToString("000 ") + identifier);
            bool recordSaved = false;

            if (string.IsNullOrWhiteSpace(identifier))
            {
                identifier = cdNewEntity.ToString();
            }
            var newOwner  = cdNewEntity.Property <EntityReference>("ownerid", null);
            var newState  = cdNewEntity.Property <OptionSetValue>("statecode", null);
            var newStatus = cdNewEntity.Property <OptionSetValue>("statuscode", null);
            var newActive = newState != null?CintEntity.GetActiveStates(cdNewEntity.Name).Contains(newState.Value) : true;

            bool nowActive = true;

            if ((newState == null) != (newStatus == null))
            {
                throw new InvalidDataException("When setting status of the record, both statecode and statuscode must be present");
            }
            if (!newActive)
            {
                log.Log("Removing state+status from entity to update");
                cdNewEntity.RemoveProperty("statecode");
                cdNewEntity.RemoveProperty("statuscode");
            }
            if (cdMatchEntity == null)
            {
                cdNewEntity.Create();
                recordSaved = true;
                SendLine("{0:000} Created: {1}", pos, identifier);
            }
            else
            {
                var oldState  = cdMatchEntity.Property <OptionSetValue>("statecode", null);
                var oldActive = oldState != null?CintEntity.GetActiveStates(cdNewEntity.Name).Contains(oldState.Value) : true;

                nowActive      = oldActive;
                cdNewEntity.Id = cdMatchEntity.Id;
                if (!oldActive && (newActive || updateInactiveRecord))
                {   // Inaktiv post som ska aktiveras eller uppdateras
                    cdNewEntity.SetState(0, 1);
                    SendLine("{0:000} Activated: {1} for update", pos, identifier);
                    nowActive = true;
                }

                if (nowActive)
                {
                    var updateattributes = cdNewEntity.Attributes.Keys.ToList();
                    if (updateattributes.Contains(cdNewEntity.PrimaryIdAttribute))
                    {
                        updateattributes.Remove(cdNewEntity.PrimaryIdAttribute);
                    }
                    if (updateIdentical || !EntityAttributesEqual(updateattributes, cdNewEntity, cdMatchEntity))
                    {
                        cdNewEntity.Update();
                        recordSaved = true;
                        SendLine("{0:000} Updated: {1}", pos, identifier);
                    }
                    else
                    {
                        SendLine("{0:000} Skipped: {1} (Identical)", pos, identifier);
                    }
                }
                else
                {
                    SendLine("{0:000} Inactive: {1}", pos, identifier);
                }
                if (newOwner != null && !newOwner.Equals(cdMatchEntity.Property("ownerid", new EntityReference())))
                {
                    cdNewEntity.Assign(newOwner);
                    SendLine("{0:000} Assigned: {1} to {2} {3}", pos, identifier, newOwner.LogicalName, string.IsNullOrEmpty(newOwner.Name) ? newOwner.Id.ToString() : newOwner.Name);
                }
            }
            if (newActive != nowActive)
            {   // Aktiv skall ändras på posten
                var newStatusValue = newStatus.Value;
                if (cdNewEntity.Name == "savedquery" && newState.Value == 1 && newStatusValue == 1)
                {   // Justering för inaktiverad men ej publicerad vy
                    newStatusValue = 2;
                }
                cdNewEntity.SetState(newState.Value, newStatusValue);
                SendLine("{0:000} SetState: {1}: {2}/{3}", pos, identifier, newState.Value, newStatus.Value);
            }
            log.EndSection();
            return(recordSaved);
        }