Получить N: N отношения Динамика CRM - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть отношения между Возможностями и моей индивидуальной сущностью Контракта в Dynamics 2016 на предпосылке. Я пытаюсь извлечь все связанные контракты из определенной возможности в плагине C #. Когда я пытаюсь получить отношения, я получаю сообщение об ошибке:

Не существует системной связи «многие ко многим» между возможностью и ccseq_contract. При попытке связать через пользовательское отношение «многие ко многим» убедитесь, что вы указали атрибуты from и to.

Похоже, что отношения существуют на основе этого скриншота:

N:N Relationship Definition

Вот мое выражение запроса:

EntityCollection contracts = service.RetrieveMultiple(new QueryExpression()
{
    EntityName = Opportunity.LogicalName,
    ColumnSet = new ColumnSet(new String[]
    {
        Opportunity.Properties.OpportunityId
    }),
    LinkEntities =
    {
        new LinkEntity
        {
            LinkFromEntityName = Opportunity.LogicalName,
            LinkToEntityName = Contract.LogicalName,
            LinkCriteria = new FilterExpression
            {
                FilterOperator = LogicalOperator.And,
                Conditions =
                {
                    new ConditionExpression
                    {
                        AttributeName = Opportunity.Properties.OpportunityId,
                        Operator = ConditionOperator.Equal,
                        Values = {wonOpportunity.Id}
                    }
                }
            }
        }
    }
});

Почему я получаю эту ошибку и как ее устранить?

Ответы [ 3 ]

0 голосов
/ 16 ноября 2018

Пожалуйста, попробуйте получить список контрактов, используя приведенный ниже XML-запрос.Запрос выполняется по отношению N: N.

<fetch  mapping='logical'>
    <entity name='ccseq_opportunity_ccseq_contract'>
        <attribute name='opportunityid'/>
        <attribute name='ccseq_contractid'/>
        <link-entity name='opportunity' to='opportunityid' from='opportunityid' alias='opportunity'>
            <attribute name='opportunityid'/>
            <filter type='and'>
                <condition attribute='opportunityid' operator='eq' value=$'{wonOpportunity.Id}'/>
            </filter>
        </link-entity>
    </entity>
</fetch>

Надеюсь, это поможет.

0 голосов
/ 16 ноября 2018

Вот где я и оказался. Это было частично основано на ответе Гнуда.

QueryExpression query = new QueryExpression("ccseq_opportunity_ccseq_contract");
query.ColumnSet.AddColumns(Contract.Properties.ContractId, Opportunity.Properties.OpportunityId);
query.Criteria = new FilterExpression();
query.Criteria.AddCondition(Opportunity.Properties.OpportunityId, ConditionOperator.Equal, wonOpportunity.Id);

EntityCollection contracts = service.RetrieveMultiple(query);
0 голосов
/ 15 ноября 2018

LinkedEntity в выражении запроса в точности похоже на внутреннее или внешнее соединение SQL (вы указываете тип соединения).он отлично подходит для извлечения отношений N: 1, он действительно не работает для N: N.

Для N: N вам нужно пройти через «сущность отношений».

Если вы хотите, чтобы все контракты были связаны с возможностью, вы должны извлечь все контакты, в которых есть строка, связывающая их с этой возможностью, в таблице «сущность отношения», «ccseq_opportunity_ccseq_contract» (я использую строковые константы ниже, потому что я нея не знаю, как вы строите свои классы сущностей).

var q = new QueryExpression("ccseq_contract") {
    ColumnSet = new ColumnSet(true), //or specify what fields you want from ccseq_contract
    LinkEntities =  {
        new LinkEntity() {              
            LinkFromEntityName = "ccseq_contract",
            LinkToEntityName = "ccseq_opportunity_ccseq_contract",
            ColumnSet = new ColumnSet(false), //don't fetch any fields from the link table
            LinkCriteria = new FilterExpression() {
                FilterOperator = LogicalOperator.And,
                Conditions = {
                    new ConditionExpression("opportunityid", ConditionOperator.Equal, wonOpportunity.Id)                    
                }
            }
        }
    }       
};

В качестве отступления, если вы не используете оператор запроса in, я бы действительно предпочел использовать запросы LINQ вместо выражений запросов., если вы создали строго типизированные классы сущностей.Запрос LINQ будет выглядеть как

using(var ctx = new OrganizationServiceContext(service)) {
    var contracts = (
        from c in ctx.CreateQuery<ccseq_contract>()
        join lnk in ctx.CreateQuery<ccseq_opportunity_ccseq_contract>() on c.ccseq_contractId equals link.ccseq_contractId
        where lnk.opportunityid = wonOpportunity.Id
        select c
        // Or, to fetch only some fields, do 
        // select new { c.ccseq_contractId, c.ccseq_name }
        ).ToList();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...