private void CompareManyToMany(OrganizationDifferenceImageBuilder imageBuilder, List <string> strDifference, string entityName, IEnumerable <ManyToManyRelationshipMetadata> listRel1, IEnumerable <ManyToManyRelationshipMetadata> listRel2)
        {
            Dictionary <string, List <string> > dictDifference = new Dictionary <string, List <string> >(StringComparer.InvariantCultureIgnoreCase);

            foreach (var rel1 in listRel1.OrderBy(s => s.SchemaName))
            {
                var rel2 = listRel2.FirstOrDefault(s => s.SchemaName == rel1.SchemaName);

                if (rel2 == null)
                {
                    continue;
                }

                if (_notExising.Contains(rel1.Entity1LogicalName) || _notExising.Contains(rel1.Entity2LogicalName))
                {
                    continue;
                }

                if (_notExising.Contains(rel2.Entity1LogicalName) || _notExising.Contains(rel2.Entity2LogicalName))
                {
                    continue;
                }

                List <string> diff = GetDifferenceManyToMany(rel1, rel2);

                if (diff.Count > 0)
                {
                    dictDifference.Add(rel1.SchemaName, diff);

                    imageBuilder.AddComponentDifferent((int)ComponentType.EntityRelationship, rel1.MetadataId.Value, rel2.MetadataId.Value, string.Join(Environment.NewLine, diff));
                }
            }

            if (dictDifference.Count > 0)
            {
                if (strDifference.Count > 0)
                {
                    strDifference.Add(string.Empty);
                }

                strDifference.Add(string.Format("ManyToMany DIFFERENT in {0} and {1}: {2}", _connectionName1, _connectionName2, dictDifference.Count));

                foreach (var item in dictDifference.OrderBy(e => e.Key))
                {
                    if (strDifference.Count > 0)
                    {
                        strDifference.Add(string.Empty);
                    }

                    strDifference.Add(string.Format("Different ManyToMany {0}", item.Key));

                    item.Value.ForEach(s => strDifference.Add(_tabSpacer + s));
                }
            }
        }
        private async Task CompareAttributes(OrganizationDifferenceImageBuilder imageBuilder, List <string> strDifference, string entityName, IEnumerable <AttributeMetadata> attributes1, IEnumerable <AttributeMetadata> attributes2)
        {
            Dictionary <string, List <string> > dictDifference = new Dictionary <string, List <string> >(StringComparer.InvariantCultureIgnoreCase);

            foreach (var attr1 in attributes1.OrderBy(s => s.LogicalName))
            {
                var attr2 = attributes2.FirstOrDefault(s => s.LogicalName == attr1.LogicalName);

                if (attr2 == null)
                {
                    continue;
                }

                List <string> diff = await GetDifferenceAttribute(attr1, attr2);

                if (diff.Count > 0)
                {
                    dictDifference.Add(attr1.LogicalName, diff);

                    imageBuilder.AddComponentDifferent((int)ComponentType.Attribute, attr1.MetadataId.Value, attr2.MetadataId.Value, string.Join(Environment.NewLine, diff));
                }
            }

            if (dictDifference.Count > 0)
            {
                if (strDifference.Count > 0)
                {
                    strDifference.Add(string.Empty);
                }

                strDifference.Add(string.Format("Attributes DIFFERENT in {0} and {1}: {2}", _connectionName1, _connectionName2, dictDifference.Count));

                foreach (var item in dictDifference.OrderBy(e => e.Key))
                {
                    if (strDifference.Count > 0)
                    {
                        strDifference.Add(string.Empty);
                    }

                    strDifference.Add(string.Format("Different Attribute {0}", item.Key));

                    item.Value.ForEach(s => strDifference.Add(_tabSpacer + s));
                }
            }
        }
        private void CompareKeys(OrganizationDifferenceImageBuilder imageBuilder, List <string> strDifference, string entityName, IEnumerable <EntityKeyMetadata> keys1, IEnumerable <EntityKeyMetadata> keys2)
        {
            Dictionary <string, List <string> > dictDifference = new Dictionary <string, List <string> >(StringComparer.InvariantCultureIgnoreCase);

            foreach (var key1 in keys1.OrderBy(s => s.LogicalName))
            {
                var key2 = keys2.FirstOrDefault(s => s.LogicalName == key1.LogicalName);

                if (key2 == null)
                {
                    continue;
                }

                List <string> diff = GetDifferenceKey(key1, key2);

                if (diff.Count > 0)
                {
                    dictDifference.Add(key1.LogicalName, diff.Select(s => _tabSpacer + s).ToList());

                    imageBuilder.AddComponentDifferent((int)ComponentType.EntityKey, key1.MetadataId.Value, key2.MetadataId.Value, string.Join(Environment.NewLine, diff));
                }
            }

            if (dictDifference.Count > 0)
            {
                if (strDifference.Count > 0)
                {
                    strDifference.Add(string.Empty);
                }

                strDifference.Add(string.Format("Keys DIFFERENT in {0} and {1}: {2}", _connectionName1, _connectionName2, dictDifference.Count));

                foreach (var item in dictDifference.OrderBy(e => e.Key))
                {
                    if (strDifference.Count > 0)
                    {
                        strDifference.Add(string.Empty);
                    }

                    strDifference.Add(string.Format("Different Keys {0}", item.Key));

                    strDifference.AddRange(item.Value);
                }
            }
        }
        public async Task <List <string> > GetDifference(OrganizationDifferenceImageBuilder imageBuilder, EntityMetadata entityMetadata1, EntityMetadata entityMetadata2)
        {
            List <string> strDifference = new List <string>();

            {
                FormatTextTableHandler table = new FormatTextTableHandler(true);

                table.CalculateLineLengths("LanguageCode", "Value");
                table.CalculateLineLengths("LanguageCode", "Organization", "Value");

                var isDifferentDisplayName = LabelComparer.GetDifference(entityMetadata1.DisplayName, entityMetadata2.DisplayName);
                var isDifferentDescription = LabelComparer.GetDifference(entityMetadata1.Description, entityMetadata2.Description);

                isDifferentDisplayName.LabelsOnlyIn1.ForEach(i => table.CalculateLineLengths(i.Locale, i.Value));
                isDifferentDisplayName.LabelsOnlyIn2.ForEach(i => table.CalculateLineLengths(i.Locale, i.Value));
                isDifferentDisplayName.LabelDifference.ForEach(i =>
                {
                    table.CalculateLineLengths(i.Locale, _connectionName1, i.Value1);
                    table.CalculateLineLengths(i.Locale, _connectionName2, i.Value2);
                });

                isDifferentDescription.LabelsOnlyIn1.ForEach(i => table.CalculateLineLengths(i.Locale, i.Value));
                isDifferentDescription.LabelsOnlyIn2.ForEach(i => table.CalculateLineLengths(i.Locale, i.Value));
                isDifferentDescription.LabelDifference.ForEach(i =>
                {
                    table.CalculateLineLengths(i.Locale, _connectionName1, i.Value1);
                    table.CalculateLineLengths(i.Locale, _connectionName2, i.Value2);
                });

                if (!isDifferentDisplayName.IsEmpty)
                {
                    if (isDifferentDisplayName.LabelsOnlyIn1.Count > 0)
                    {
                        strDifference.Add(string.Format("DisplayNames ONLY in {0}: {1}", _connectionName1, isDifferentDisplayName.LabelsOnlyIn1.Count));
                        strDifference.Add(_tabSpacer + table.FormatLine("LanguageCode", "Value"));
                        isDifferentDisplayName.LabelsOnlyIn1.ForEach(e => strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, e.Value)));
                    }

                    if (isDifferentDisplayName.LabelsOnlyIn2.Count > 0)
                    {
                        strDifference.Add(string.Format("DisplayNames ONLY in {0}: {1}", _connectionName2, isDifferentDisplayName.LabelsOnlyIn2.Count));
                        strDifference.Add(_tabSpacer + table.FormatLine("LanguageCode", "Value"));
                        isDifferentDisplayName.LabelsOnlyIn2.ForEach(e => strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, e.Value)));
                    }

                    if (isDifferentDisplayName.LabelDifference.Count > 0)
                    {
                        strDifference.Add(string.Format("DisplayNames DIFFERENT in {0} and {1}: {2}", _connectionName1, _connectionName2, isDifferentDisplayName.LabelDifference.Count));
                        strDifference.Add(_tabSpacer + table.FormatLine("LanguageCode", "Organization", "Value"));
                        isDifferentDisplayName.LabelDifference.ForEach(e =>
                        {
                            strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, _connectionName1, e.Value1));
                            strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, _connectionName2, e.Value2));
                        });
                    }
                }

                if (!isDifferentDescription.IsEmpty)
                {
                    if (isDifferentDescription.LabelsOnlyIn1.Count > 0)
                    {
                        strDifference.Add(string.Format("Descriptions ONLY in {0}: {1}", _connectionName1, isDifferentDescription.LabelsOnlyIn1.Count));
                        strDifference.Add(_tabSpacer + table.FormatLine("LanguageCode", "Value"));
                        isDifferentDescription.LabelsOnlyIn1.ForEach(e => strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, e.Value)));
                    }

                    if (isDifferentDescription.LabelsOnlyIn2.Count > 0)
                    {
                        strDifference.Add(string.Format("Descriptions ONLY in {0}: {1}", _connectionName2, isDifferentDescription.LabelsOnlyIn2.Count));
                        strDifference.Add(_tabSpacer + table.FormatLine("LanguageCode", "Value"));
                        isDifferentDescription.LabelsOnlyIn2.ForEach(e => strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, e.Value)));
                    }

                    if (isDifferentDescription.LabelDifference.Count > 0)
                    {
                        strDifference.Add(string.Format("Descriptions DIFFERENT in {0} and {1}: {2}", _connectionName1, _connectionName2, isDifferentDescription.LabelDifference.Count));
                        strDifference.Add(_tabSpacer + table.FormatLine("LanguageCode", "Organization", "Value"));
                        isDifferentDescription.LabelDifference.ForEach(e =>
                        {
                            strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, _connectionName1, e.Value1));
                            strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, _connectionName2, e.Value2));
                        });
                    }
                }
            }

            {
                FormatTextTableHandler table = new FormatTextTableHandler(true);

                table.CalculateLineLengths("LanguageCode", "Value");
                table.CalculateLineLengths("LanguageCode", "Organization", "Value");

                var isDifferentDisplayCollectionName = LabelComparer.GetDifference(entityMetadata1.DisplayCollectionName, entityMetadata2.DisplayCollectionName);

                isDifferentDisplayCollectionName.LabelsOnlyIn1.ForEach(i => table.CalculateLineLengths(i.Locale, i.Value));
                isDifferentDisplayCollectionName.LabelsOnlyIn2.ForEach(i => table.CalculateLineLengths(i.Locale, i.Value));
                isDifferentDisplayCollectionName.LabelDifference.ForEach(i =>
                {
                    table.CalculateLineLengths(i.Locale, _connectionName1, i.Value1);
                    table.CalculateLineLengths(i.Locale, _connectionName2, i.Value2);
                });

                if (!isDifferentDisplayCollectionName.IsEmpty)
                {
                    if (isDifferentDisplayCollectionName.LabelsOnlyIn1.Count > 0)
                    {
                        strDifference.Add(string.Format("DisplayCollectionNames ONLY in {0}: {1}", _connectionName1, isDifferentDisplayCollectionName.LabelsOnlyIn1.Count));
                        strDifference.Add(_tabSpacer + table.FormatLine("LanguageCode", "Value"));
                        isDifferentDisplayCollectionName.LabelsOnlyIn1.ForEach(e => strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, e.Value)));
                    }

                    if (isDifferentDisplayCollectionName.LabelsOnlyIn2.Count > 0)
                    {
                        strDifference.Add(string.Format("DisplayCollectionNames ONLY in {0}: {1}", _connectionName2, isDifferentDisplayCollectionName.LabelsOnlyIn2.Count));
                        strDifference.Add(_tabSpacer + table.FormatLine("LanguageCode", "Value"));
                        isDifferentDisplayCollectionName.LabelsOnlyIn2.ForEach(e => strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, e.Value)));
                    }

                    if (isDifferentDisplayCollectionName.LabelDifference.Count > 0)
                    {
                        strDifference.Add(string.Format("DisplayCollectionNames DIFFERENT in {0} and {1}: {2}", _connectionName1, _connectionName2, isDifferentDisplayCollectionName.LabelDifference.Count));
                        strDifference.Add(_tabSpacer + table.FormatLine("LanguageCode", "Organization", "Value"));
                        isDifferentDisplayCollectionName.LabelDifference.ForEach(e =>
                        {
                            strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, _connectionName1, e.Value1));
                            strDifference.Add(_tabSpacer + table.FormatLine(e.Locale, _connectionName2, e.Value2));
                        });
                    }
                }
            }

            await CompareAttributes(imageBuilder, strDifference, entityMetadata1.LogicalName, entityMetadata1.Attributes, entityMetadata2.Attributes);

            CompareKeys(imageBuilder, strDifference, entityMetadata1.LogicalName, entityMetadata1.Keys ?? Enumerable.Empty <EntityKeyMetadata>(), entityMetadata2.Keys ?? Enumerable.Empty <EntityKeyMetadata>());

            CompareOneToMany(imageBuilder, strDifference, entityMetadata1.LogicalName, "N:1", "ManyToOne", entityMetadata1.ManyToOneRelationships, entityMetadata2.ManyToOneRelationships);

            CompareOneToMany(imageBuilder, strDifference, entityMetadata1.LogicalName, "1:N", "OneToMany", entityMetadata1.OneToManyRelationships, entityMetadata2.OneToManyRelationships);

            CompareManyToMany(imageBuilder, strDifference, entityMetadata1.LogicalName, entityMetadata1.ManyToManyRelationships, entityMetadata2.ManyToManyRelationships);

            return(strDifference);
        }