Как скопировать атрибут поиска в другой CRM, используя EntityMetadata? - PullRequest
0 голосов
/ 10 января 2019

Я пытаюсь скопировать поля поиска из CRM в другую CRM. Но это не удается, потому что обычно я получаю исключение, говорящее, что атрибут с логическим именем поиска не существует.

Хорошо, я знаю это, потому что я пытаюсь создать это. Когда это происходит, ссылочный атрибут отношения является поиском, поэтому поиск должен быть в ссылочном атрибуте.

Но я пытаюсь найти отношения, которые имеют логическое имя поиска в указанном атрибуте, и я не нахожу, я пробовал OneToMany и ManyToOne обеих сущностей. Поэтому мне нужна помощь, чтобы решить эту проблему. У кого-нибудь есть решение?

Я не хочу решать эту проблему с помощью решений, поскольку решения не могут копировать управляемые поля поиска. И у меня есть все атрибуты и сущности, которые нужно создать в другой CRM, мне нужно только создать поиск и ваши отношения.

У меня есть этот базовый код, но для его проверки необходимы 2 CRM.

public void CopyLookup() {

        List<EntityMetadata> OriginEntities = new List<EntityMetadata>();

        bool sucess = false;

        while (!sucess) {
            try {

                RetrieveAllEntitiesRequest metaDataRequest = new RetrieveAllEntitiesRequest();
                metaDataRequest.EntityFilters = EntityFilters.All;

                // Execute the request.

                RetrieveAllEntitiesResponse metaDataResponse = (RetrieveAllEntitiesResponse)Origin.IOrganizationService.Execute(metaDataRequest);
                OriginEntities = new List<EntityMetadata>(metaDataResponse.EntityMetadata);
                sucess = true;
                return entitiesMetadata;

            } catch (ThreadAbortException) {
            } catch (Exception _ex) {
                Console.WriteLine(String.Format("Fail to find Entities - {0}", _ex.Message));
                if (_ex.Message.Contains("There was no endpoint"))
                    sucess = false;
                else
                    throw new Exception(String.Format("Fail to find Entities - {0}", _ex.Message));
            }
        }


        foreach (EntityMetadata ent in OriginEntities.Where(wh => wh.LogicalName.Contains('_'))) {

                foreach (OneToManyRelationshipMetadata relation in ent.OneToManyRelationships) {

                    LookupAttributeMetadata lookup = (LookupAttributeMetadata)OriginEntities.Where(wh => relation.ReferencingEntity == wh.LogicalName).FirstOrDefault()
                                                                             .Attributes.Where(wa => wa.AttributeType == AttributeTypeCode.Lookup && wa.LogicalName == relation.ReferencingAttribute).FirstOrDefault();

                    if (lookup == null)
                        continue;

                    CreateOneToManyRequest createOtm = new CreateOneToManyRequest() {
                        OneToManyRelationship = relation,
                        Lookup = lookup
                    };

                    bool sucess2 = false;

                    while (!sucess2) {

                        try {
                            Migration.IOrganizationService.Execute(createOtm);
                        } catch (EndpointNotFoundException) {
                            sucess2 = false;
                        } catch (TimeoutException) {
                            sucess2 = false;
                        } catch (FaultException ex) {
                            if (ex.Message.Contains("endpoint")) {
                                sucess2 = false;
                            } else if (ex.Message.Contains("there is already")) {
                                sucess2 = true;
                            } else {
                                sucess2 = true;
                            }
                        } catch (Exception ex) {
                            if (ex.Message.Contains("This could be due to the service endpoint binding")) {
                                sucess2 = false;
                            } else if (ex.Message.Contains("is not unique")) {
                                sucess2 = true;
                            } else {
                                sucess2 = true;
                            }
                        }
                    }
                }
            }
        }

1 Ответ

0 голосов
/ 11 января 2019

Я всегда создавал отношения вручную или с помощью решения, но я взглянул на ваш код и получил несколько идей, которые могут помочь ...

Этот код отражает некоторые из этих идей, с дополнительной информацией ниже.

var metaDataRequest = new RetrieveAllEntitiesRequest
{
    EntityFilters = EntityFilters.All
};

var metaDataResponse = (RetrieveAllEntitiesResponse)svc.Execute(metaDataRequest);
var OriginEntities = metaDataResponse.EntityMetadata.ToList();

foreach (var entity in OriginEntities.Where(e=> e.IsCustomizable.Value))
{
    foreach (var relationship in entity.OneToManyRelationships.Where(r => r.IsCustomRelationship == true))
    {
        var lookup = OriginEntities
            .Where(e => e.LogicalName == relationship.ReferencingEntity)
            .Single()
            .Attributes
            .Where(a => a.AttributeType == AttributeTypeCode.Lookup && a.LogicalName == relationship.ReferencingAttribute)
            .Single();
        var createOtm = new CreateOneToManyRequest()
        {
            OneToManyRelationship = relationship,
            Lookup = lookup as LookupAttributeMetadata
        };
    }
}
  1. Я думаю, что вы хотите иметь дело только с настраиваемыми объектами и настраиваемыми отношениями к ним, поэтому я изменил предложения Where в циклах foreach.
  2. Если вы хотите сделать копии управляемых полей поиска, я думаю, вы захотите сбросить флаг IsManaged отношения на false и его значение IsCustomizable на true. isManaged isCustomizable
  3. Как только вы вручную создадите отношения решения как неуправляемые, вы никогда не сможете установить управляемое решение в этой системе. Итак, мне интересно, является ли создание управляемых полей поиска с помощью кода хорошей практикой в ​​долгосрочной перспективе. Почему бы вместо этого не установить управляемое решение в целевой системе миграции?
  4. Прежде чем пытаться скопировать отношение 1: N, вы можете попробовать создать его с нуля в коде, чтобы увидеть, какая информация действительно требуется. Это может помочь вам сократить то, что вы извлекаете, до минимума того, что вам нужно для его создания. Например, ColumnNumber атрибута доступен только для чтения, и загруженные данные имеют его. Если вы создали новый атрибут с нуля, он должен быть пустым.
  5. В долгосрочной перспективе такой подход может принести больше хлопот, чем стоит. Например, если ваша организация начинает использовать больше сред песочницы, и вам нужно запускать код каждый раз, когда вы хотите его настроить. Возможно, пересмотрите возможность использования решений или использования гибридного подхода для создания нескольких поисков в коде, а остальное с помощью решений.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...