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);
        }
        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);
        }
        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 void AddFilter(QueryExpression qExport, DataBlockExportFilter filter)
        {
            var valuestring = filter.Value;

            if (valuestring.Contains("{0}"))
            {
                throw new ArgumentOutOfRangeException("Name", "Filter", "Parameterized Filters not supported in embedded Shuffle Utils");
            }
            var operstr = filter.Operator.ToString();

            if (string.IsNullOrEmpty(operstr))
            {
                operstr = "Equal";
            }
            var oper = (Microsoft.Xrm.Sdk.Query.ConditionOperator)Enum.Parse(typeof(Microsoft.Xrm.Sdk.Query.ConditionOperator), operstr, true);

            object value = null;

            if (oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.EqualBusinessId &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.EqualUserId &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.EqualUserLanguage &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.NotEqualBusinessId &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.NotEqualUserId &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.NotNull &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.Null &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.ThisMonth &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.ThisWeek &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.ThisYear &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.Today &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.Tomorrow &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.Yesterday)
            {
                if (filter.TypeSpecified)
                {
                    switch (filter.Type)
                    {
                    case FilterTypes.@string:
                        value = valuestring;
                        break;

                    case FilterTypes.@int:
                        value = int.Parse(valuestring);
                        break;

                    case FilterTypes.@bool:
                        value = bool.Parse(valuestring);
                        break;

                    case FilterTypes.datetime:
                        value = DateTime.Parse(valuestring);
                        break;

                    case FilterTypes.guid:
                        value = new Guid(valuestring);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException("Type", filter.Type, "Invalid filter attribute type");
                    }
                }
            }
            var attribute = filter.Attribute;

            log.Log("Adding filter: {0} {1} {2}", attribute, oper, value);
            CintQryExp.AppendCondition(qExport.Criteria, LogicalOperator.And, attribute, oper, value);
        }
        private CintDynEntityCollection ExportDataBlock(ShuffleBlocks blocks, XmlNode xBlock)
        {
            log.StartSection("ExportDataBlock");
            string name = CintXML.GetAttribute(xBlock, "Name");

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

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

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

                #region Define attributes

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

                #endregion Define attributes

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

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

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

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

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

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

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

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

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

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

                    #endregion FetchXML Intersect
                }

                log.Log("Returning {0} records", cExportEntities.Count);
            }
            log.EndSection();
            return(cExportEntities);
        }
        private void AddFilter(QueryExpression qExport, XmlNode xExpProp)
        {
            string valuestring = CintXML.GetAttribute(xExpProp, "Value");

            if (valuestring.Contains("{0}"))
            {
                throw new ArgumentOutOfRangeException("Name", "Filter", "Parameterized Filters not supported in embedded Shuffle Utils");
            }
            string operstr = CintXML.GetAttribute(xExpProp, "Operator");

            if (string.IsNullOrEmpty(operstr))
            {
                operstr = "Equal";
            }
            Microsoft.Xrm.Sdk.Query.ConditionOperator oper = (Microsoft.Xrm.Sdk.Query.ConditionOperator)Enum.Parse(typeof(Microsoft.Xrm.Sdk.Query.ConditionOperator), operstr, true);

            object value = null;

            if (oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.EqualBusinessId &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.EqualUserId &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.EqualUserLanguage &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.NotEqualBusinessId &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.NotEqualUserId &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.NotNull &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.Null &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.ThisMonth &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.ThisWeek &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.ThisYear &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.Today &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.Tomorrow &&
                oper != Microsoft.Xrm.Sdk.Query.ConditionOperator.Yesterday)
            {
                switch (CintXML.GetAttribute(xExpProp, "Type").ToUpperInvariant())
                {
                case "STRING":
                    value = valuestring;
                    break;

                case "INT":
                    value = int.Parse(valuestring);
                    break;

                case "BOOL":
                    value = bool.Parse(valuestring);
                    break;

                case "DATETIME":
                    value = DateTime.Parse(valuestring);
                    break;

                case "GUID":
                    value = new Guid(valuestring);
                    break;

                default:
                    throw new ArgumentOutOfRangeException("Type", CintXML.GetAttribute(xExpProp, "Type"), "Invalid filter attribute type");
                }
            }
            string attribute = CintXML.GetAttribute(xExpProp, "Attribute");

            log.Log("Adding filter: {0} {1} {2}", attribute, oper, value);
            CintQryExp.AppendCondition(qExport.Criteria, LogicalOperator.And, attribute, oper, value);
        }