检索N:N关系Dynamics CRM

时间:2018-11-15 15:28:52

标签: c# dynamics-crm microsoft-dynamics

在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}
                    }
                }
            }
        }
    }
});

我为什么会收到此错误?如何解决该错误?

4 个答案:

答案 0 :(得分:1)

查询表达式中的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();
}

答案 1 :(得分:1)

另一个答案,可以使查询的逻辑在视觉上更易于理解。像在sql中那样思考,首先切换到中间表,然后切换到其他表

        QueryExpression query = new QueryExpression("ccseq_contract")
        {
            ColumnSet = new ColumnSet(true),
            LinkEntities =
            {
                new LinkEntity
                {
                    LinkFromEntityName = "ccseq_contract",
                    LinkToEntityName = "ccseq_opportunity_ccseq_contract",
                    LinkFromAttributeName = "ccseq_contractId",
                    LinkToAttributeName = "ccseq_contractId",
                    LinkEntities =
                    {
                        new LinkEntity
                        {
                            LinkFromEntityName = "ccseq_opportunity_ccseq_contract",
                            LinkToEntityName = "opportunity",
                            LinkFromAttributeName = "opportunityid",
                            LinkToAttributeName = "opportunityid",
                            LinkCriteria = new FilterExpression
                            {
                                Conditions =
                                {
                                    new ConditionExpression("opportunityid", ConditionOperator.Equal, wonOpportunity.Id)
                                }
                            }
                        }
                    }
                }
            }
        };

答案 2 :(得分:0)

请尝试使用以下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>

希望有帮助。

答案 3 :(得分:0)

这就是我的结局。这部分是基于gnud的回答。

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);