我正在尝试编写一种通用方法,该方法给定任何Dynamics 365实体名称,并且一组ID(GUIDS)将以与该枚举集匹配的一组实体记录进行响应。我感到沮丧的是,似乎没有一种有效的方法来使API能够简单地使用“主ID密钥”而不先从元数据中获取它,这是另一次(看似不必要的)往返。
请考虑以下(破解)方法:
public EntityCollection HackedFetchEntityRecordsById(IOrganizationService orgSvc, string entityName, IEnumerable<Guid> primaryEntityAttributeIds)
{
// Defacto HACK for getting primary entity attribute
string primaryEntityAttribute = $"{entityName}id";
StringBuilder sb = new StringBuilder();
foreach (Guid guid in primaryEntityAttributeIds)
{
sb.AppendLine($@"<value>{guid}</value>");
}
string fetchXml = $@"
<fetch mapping='logical'>
<entity name='{entityName}'>
<no-attrs />
<filter>
<condition attribute='{primaryEntityAttribute}' operator='in'>
{sb}
</condition>
</filter>
</entity>
</fetch> ";
return orgSvc.RetrieveMultiple(new FetchExpression(fetchXml));
}
请注意,这里我只是使用观察到的事实上的标准,因为微软似乎选择使用实体名称后跟字符串“ id”来命名实体上的主要id属性。这显然是不安全的,也是一种糟糕的方法。
我可以以“正确”的方式做到这一点,但是效率低下:
public EntityCollection InefficientFetchEntityRecordsById(IOrganizationService orgSvc, string entityName, IEnumerable<Guid> primaryEntityAttributeIds)
{
// "Correct" but inefficient way of getting primary entity attribute
string primaryEntityAttribute = ((RetrieveEntityResponse) orgSvc.Execute(new RetrieveEntityRequest
{
LogicalName = entityName
})).EntityMetadata.PrimaryIdAttribute;
StringBuilder sb = new StringBuilder();
foreach (Guid guid in primaryEntityAttributeIds)
{
sb.AppendLine($@"<value>{guid}</value>");
}
string fetchXml = $@"
<fetch mapping='logical'>
<entity name='{entityName}'>
<no-attrs />
<filter>
<condition attribute='{primaryEntityAttribute}' operator='in'>
{sb}
</condition>
</filter>
</entity>
</fetch> ";
return orgSvc.RetrieveMultiple(new FetchExpression(fetchXml));
}
请注意,在这种情况下,我需要进行单独的服务调用(包括所有开销)以获取实体元数据,以便辨别主要属性是什么。好吧。
我想做类似下面的方法(幻想/不起作用):
public EntityCollection FantasyFetchEntityRecordsById(IOrganizationService orgSvc, string entityName, IEnumerable<Guid> primaryEntityAttributeIds)
{
StringBuilder sb = new StringBuilder();
foreach (Guid guid in primaryEntityAttributeIds)
{
sb.AppendLine($@"<value>{guid}</value>");
}
// ILLEGAL XML - made up element "primaryEntityAttribute"
string fetchXml = $@"
<fetch mapping='logical'>
<entity name='{entityName}'>
<no-attrs />
<filter>
<primaryEntityAttribute operator='in'>
{sb}
</primaryEntityAttribute>
</filter>
</entity>
</fetch> ";
return orgSvc.RetrieveMultiple(new FetchExpression(fetchXml));
}
我很高兴在RetrieveMultiple服务中使用QueryBase的其他实现。
答案 0 :(得分:1)
由于“ hacked”方法在大多数情况下都可以工作,因此也许可以通过在实体名称后附加id
来尝试“ hacked”方法。如果失败,则检索实体元数据以获取primaryId。
答案 1 :(得分:0)
创建实体时,主键由CRM设置,并且遵循“实体名称” +“ id”,following this format isn't a hack的格式。
如果您对此不满意,我将使用元数据服务一次批量检索详细信息。
RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest()
{
EntityFilters = EntityFilters.Entity,
RetrieveAsIfPublished = true
};
RetrieveAllEntitiesResponse response = (RetrieveAllEntitiesResponse)_serviceProxy.Execute(request);
foreach (EntityMetadata currentEntity in response.EntityMetadata)
{
currentEntity.PrimaryIdAttribute
}
我不确定这样做有什么问题,大概是您为每个实体进行了多次服务调用,一个额外的元数据调用不会受到影响。至于期望服务器“只知道”此信息;仍然可能必须查询元数据表。
最后,如果有人必须向您提供实体名称,您也可以要求提供主键字段。