检索 N:N 关系 Dynamics CRM
Retrieve N:N relationship Dynamics CRM
我在内部部署的 Dynamics 2016 中的机会和我的自定义合同实体之间存在关系。我正在尝试从 C# 插件中的特定机会检索所有相关合同。当我尝试检索关系时,收到错误:
No system many-to-many relationship exists between opportunity and ccseq_contract. If attempting to link through a custom many-to-many relationship ensure that you provide the from and to attributes.
根据此屏幕截图看来关系确实存在:
这是我的查询表达式:
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}
}
}
}
}
}
});
为什么我会收到此错误以及如何解决该错误?
查询表达式中的 LinkedEntity
与 SQL 内部或外部联接完全相同(您指定联接类型)。
它非常适合获取 N:1 关系,但它不适用于 N:N。
对于 N:N,您需要通过 'relationship entity'。
如果您希望所有合同都链接到一个机会,
您必须在 'relationship entity' table、'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();
}
请尝试使用以下 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>
希望对您有所帮助。
这是我结束的地方。这部分基于 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);
另一个可以使查询逻辑在视觉上更易理解的答案。像sql中那样思考,先切换到中间table,然后切换到其他table
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)
}
}
}
}
}
}
};
我在内部部署的 Dynamics 2016 中的机会和我的自定义合同实体之间存在关系。我正在尝试从 C# 插件中的特定机会检索所有相关合同。当我尝试检索关系时,收到错误:
No system many-to-many relationship exists between opportunity and ccseq_contract. If attempting to link through a custom many-to-many relationship ensure that you provide the from and to attributes.
根据此屏幕截图看来关系确实存在:
这是我的查询表达式:
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}
}
}
}
}
}
});
为什么我会收到此错误以及如何解决该错误?
查询表达式中的 LinkedEntity
与 SQL 内部或外部联接完全相同(您指定联接类型)。
它非常适合获取 N:1 关系,但它不适用于 N:N。
对于 N:N,您需要通过 'relationship entity'。
如果您希望所有合同都链接到一个机会, 您必须在 'relationship entity' table、'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();
}
请尝试使用以下 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>
希望对您有所帮助。
这是我结束的地方。这部分基于 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);
另一个可以使查询逻辑在视觉上更易理解的答案。像sql中那样思考,先切换到中间table,然后切换到其他table
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)
}
}
}
}
}
}
};