private static void SelectAttributes(CintDynEntityCollection cExportEntities, List <string> lAttributes, List <string> lNullAttributes)
 {
     foreach (var cde in cExportEntities)
     {
         var i = 0;
         var x = new List <string>(cde.Attributes.Keys);
         while (i < cde.Attributes.Count)
         {
             var attr = x[i];
             if (attr != cde.PrimaryIdAttribute && !IncludeAttribute(attr, lAttributes))
             {
                 cde.Attributes.Remove(attr);
                 x.Remove(attr);
             }
             else
             {
                 i++;
             }
         }
         foreach (var nullattribute in lNullAttributes)
         {
             if (!cde.Contains(nullattribute))
             {
                 cde.Entity.Attributes.Add(nullattribute, null);
             }
         }
     }
 }
Esempio n. 2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="blocks"></param>
        /// <param name="type"></param>
        /// <param name="delimeter"></param>
        /// <returns></returns>
        public Dictionary <string, XmlDocument> SplitFiles(ShuffleBlocks blocks, SerializationType type, char delimeter)
        {
            log.StartSection("Start SplitFiles");

            var dictionarySplitFiles = new Dictionary <string, XmlDocument>();

            if (blocks.Count > 0)
            {
                foreach (var blockName in blocks.Keys)
                {
                    var block = blocks[blockName];

                    foreach (var item in block)
                    {
                        //Build path to use later when writing to disk
                        string path = blockName;
                        path += "\\" + item.Id;

                        // Somehow create a single entity record shuffleBlock
                        var singleShuffleBlock = new ShuffleBlocks();
                        var entityCollection   = new CintDynEntityCollection();
                        singleShuffleBlock.Add(blockName, entityCollection);

                        entityCollection.Add(item);

                        dictionarySplitFiles.Add(path, Serialize(singleShuffleBlock, type, delimeter));
                    }
                }
            }
            log.EndSection();
            return(dictionarySplitFiles);
        }
        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);
        }
Esempio n. 4
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);
        }
        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);
        }
        internal static void AddToSolution(this CintContainer container, CintDynEntityCollection resources, string solutionUniqueName)
        {
            foreach (var resource in resources)
            {
                var request = new AddSolutionComponentRequest
                {
                    AddRequiredComponents = false,
                    ComponentId           = resource.Id,
                    ComponentType         = SolutionComponentType.WebResource,
                    SolutionUniqueName    = solutionUniqueName
                };

                container.Service.Execute(request);
            }
        }
        private List <string> GetUpdateAttributes(CintDynEntityCollection entities)
        {
            var result = new List <string>();

            foreach (var entity in entities)
            {
                foreach (var attribute in entity.Attributes.Keys)
                {
                    if (!result.Contains(attribute))
                    {
                        result.Add(attribute);
                    }
                }
            }
            return(result);
        }
        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 CintDynEntity GetAndVerifySolutionForExport(string name)
        {
            CintDynEntityCollection 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");
            }
            CintDynEntity cdSolution = cSolutions[0];

            return(cdSolution);
        }
 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 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);
        }
 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;
         }
     });
 }
        internal static void PublishWebResources(this CintContainer container, CintDynEntityCollection resources)
        {
            try
            {
                string idsXml = string.Empty;

                foreach (var resource in resources)
                {
                    idsXml += string.Format("<webresource>{0}</webresource>", resource.Id.ToString("B"));
                }

                var pxReq1 = new PublishXmlRequest
                {
                    ParameterXml = string.Format("<importexportxml><webresources>{0}</webresources></importexportxml>", idsXml)
                };

                container.Service.Execute(pxReq1);
            }
            catch (Exception error)
            {
                throw new Exception("Error while publishing web resources: " + error.Message);
            }
        }
        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));
        }
Esempio n. 15
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);
        }
Esempio n. 16
0
        /// <summary>
        /// Deserialize xml/string to blocks with entities
        /// </summary>
        /// <param name="serialized"></param>
        /// <returns>Optional, only required for SerializationType: Text</returns>
        public ShuffleBlocks Deserialize(XmlDocument serialized)
        {
            log.StartSection("Deserialize");
            ShuffleBlocks result = new ShuffleBlocks();

            if (serialized != null)
            {
                XmlNode root    = CintXML.FindChild(serialized, "ShuffleData");
                string  sertype = CintXML.GetAttribute(root, "Type");
                SendLine("Deserialize from {0}", sertype);
                if (sertype == SerializationType.Full.ToString() ||
                    sertype == SerializationType.Simple.ToString() ||
                    sertype == SerializationType.SimpleNoId.ToString() ||
                    sertype == SerializationType.SimpleWithValue.ToString() ||
                    sertype == SerializationType.Explicit.ToString())
                {
                    foreach (XmlNode xBlock in root.ChildNodes)
                    {
                        if (xBlock.NodeType == XmlNodeType.Element && xBlock.Name == "Block" && xBlock.ChildNodes.Count == 1)
                        {
                            string      name = CintXML.GetAttribute(xBlock, "Name");
                            XmlDocument xml  = new XmlDocument();
                            xml.AppendChild(xml.ImportNode(xBlock.ChildNodes[0], true));
                            CintDynEntityCollection cEntities = new CintDynEntityCollection(xml, crmsvc, log);
                            SendLine("Block {0}: {1} records", name, cEntities.Count);
                            result.Add(name, cEntities);
                        }
                    }
                }
                else if (sertype == SerializationType.Text.ToString())
                {
                    string        strdelimeter    = CintXML.GetAttribute(root, "Delimeter");
                    char          delimeter       = strdelimeter.Length == 1 ? strdelimeter[0] : '\t';
                    XmlNode       xText           = CintXML.FindChild(root, "Text");
                    StringReader  reader          = new StringReader(xText.InnerText);
                    int           line            = 0;
                    string        name            = "";
                    StringBuilder serializedblock = null;
                    string        current         = reader.ReadLine();
                    while (current != null)
                    {
                        log.Log("Line {0:000}: {1}", line, current);
                        if (current.StartsWith("<<<") && current.Contains(">>>"))
                        {
                            log.Log("Block start");
                            if (!string.IsNullOrWhiteSpace(name) && serializedblock != null)
                            {
                                CintDynEntityCollection cEntities = new CintDynEntityCollection(serializedblock.ToString(), delimeter, crmsvc, log);
                                result.Add(name, cEntities);
                                SendLine("Block {0}: {1} records", name, cEntities.Count);
                            }
                            name            = current.Substring(3);
                            name            = name.Substring(0, name.IndexOf(">>>", StringComparison.Ordinal));
                            serializedblock = new StringBuilder();
                        }
                        else
                        {
                            serializedblock.AppendLine(current);
                        }
                        current = reader.ReadLine();
                        line++;
                    }
                    if (!string.IsNullOrWhiteSpace(serializedblock.ToString()))
                    {
                        CintDynEntityCollection cEntities = new CintDynEntityCollection(serializedblock.ToString(), delimeter, crmsvc, log);
                        result.Add(name, cEntities);
                        SendLine("Block {0}: {1} records", name, cEntities.Count);
                    }
                }
            }
            log.EndSection();
            return(result);
        }
        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);
        }
        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);
        }
Esempio n. 19
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 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 ValidatePreReqs(XmlNode xImport, Version thisversion)
        {
            log.StartSection("ValidatePreReqs");
            XmlNode xPreReqs = CintXML.FindChild(xImport, "PreRequisites");

            if (xPreReqs != null)
            {
                CintDynEntityCollection cSolutions = GetExistingSolutions();
                foreach (XmlNode xPreReq in xPreReqs.ChildNodes)
                {
                    if (xPreReq.NodeType == XmlNodeType.Element && xPreReq.Name == "Solution")
                    {
                        bool   valid    = false;
                        string name     = CintXML.GetAttribute(xPreReq, "Name");
                        string comparer = CintXML.GetAttribute(xPreReq, "Comparer");
                        var    version  = new Version();
                        log.Log("Prereq: {0} {1} {2}", name, comparer, version);

                        if (comparer.Contains("this"))
                        {
                            version  = thisversion;
                            comparer = comparer.Replace("-this", "");
                        }
                        else if (comparer != "any")
                        {
                            version = new Version(CintXML.GetAttribute(xPreReq, "Version").Replace('*', '0'));
                        }

                        foreach (CintDynEntity cdSolution in cSolutions)
                        {
                            if (cdSolution.Property("uniquename", "") == name)
                            {
                                log.Log("Found matching solution");
                                switch (comparer)
                                {
                                case "any":
                                    valid = true;
                                    break;

                                case "eq":
                                    valid = new Version(cdSolution.Property("version", "1.0.0.0")).Equals(version);
                                    break;

                                case "ge":
                                    valid = new Version(cdSolution.Property("version", "<undefined>")) >= version;
                                    break;

                                default:
                                    throw new ArgumentOutOfRangeException("Comparer", comparer, "Invalid comparer value");
                                }
                            }
                            if (valid)
                            {
                                break;
                            }
                        }
                        if (valid)
                        {
                            SendLine("Prerequisite {0} {1} {2} is satisfied", name, comparer, version);
                        }
                        else
                        {
                            SendLine("Prerequisite {0} {1} {2} is NOT satisfied", name, comparer, version);
                            throw new Exception("Prerequisite NOT satisfied (" + name + " " + comparer + " " + version + ")");
                        }
                    }
                }
            }
            else
            {
                log.Log("No prereqs for solution import");
            }
            log.EndSection();
        }