C# 如何使用Dynamics 365 XRM Tooling SDK按主id一般获取枚举的实体记录集

C# 如何使用Dynamics 365 XRM Tooling SDK按主id一般获取枚举的实体记录集,c#,dynamics-crm,fetchxml,dynamics-crm-365,C#,Dynamics Crm,Fetchxml,Dynamics Crm 365,我试图编写一个通用方法,在给定任何Dynamics 365实体名称和一组ID(GUID)时,该方法将使用一组与枚举集匹配的实体记录进行响应。我感到沮丧的是,似乎没有一种有效的方法可以让API简单地使用“主ID密钥”,而不首先从元数据获取它,这是另一种(似乎不必要的)往返 考虑以下(黑客)方法: public EntityCollection HackedFetchEntityRecordsById(IOOrganizationService orgSvc,string entityName,IE

我试图编写一个通用方法,在给定任何Dynamics 365实体名称和一组ID(GUID)时,该方法将使用一组与枚举集匹配的实体记录进行响应。我感到沮丧的是,似乎没有一种有效的方法可以让API简单地使用“主ID密钥”,而不首先从元数据获取它,这是另一种(似乎不必要的)往返

考虑以下(黑客)方法:

public EntityCollection HackedFetchEntityRecordsById(IOOrganizationService orgSvc,string entityName,IEnumerable PrimaryEntityAttributeId)
{
//获取主实体属性的事实黑客
字符串primaryEntityAttribute=$“{entityName}id”;
StringBuilder sb=新的StringBuilder();
foreach(PrimaryEntityAttributeId中的Guid)
{
sb.AppendLine($@“{guid}”);
}
字符串fetchXml=$@”
{sb}
";
返回orgSvc.RetrieveMultiple(新的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低效fetchentityrecordsbyid(IOrganizationService orgSvc,string entityName,IEnumerable primaryEntityAttributeIds)
{
//获取主实体属性的“正确”但效率低下的方法
字符串primaryEntityAttribute=((RetrieveEntityResponse)orgSvc.Execute(new RetrieveEntityRequest
{
LogicalName=entityName
})).EntityMetadata.PrimaryDatAttribute;
StringBuilder sb=新的StringBuilder();
foreach(PrimaryEntityAttributeId中的Guid)
{
sb.AppendLine($@“{guid}”);
}
字符串fetchXml=$@”
{sb}
";
返回orgSvc.RetrieveMultiple(新的FetchExpression(fetchXml));
}
请注意,在这种情况下,我需要进行一个单独的服务调用(包括所需的所有开销)来获取实体元数据,以便识别主属性是什么。恶心

我想采用以下(幻想/不工作)方法:

public EntityCollection FantasyFetchEntityRecordsById(IOrganizationService orgSvc,string entityName,IEnumerable primaryEntityAttributeIds)
{
StringBuilder sb=新的StringBuilder();
foreach(PrimaryEntityAttributeId中的Guid)
{
sb.AppendLine($@“{guid}”);
}
//非法XML-组成元素“primaryEntityAttribute”
字符串fetchXml=$@”
{sb}
";
返回orgSvc.RetrieveMultiple(新的FetchExpression(fetchXml));
}

我很乐意在RetrieveMultiple服务中使用QueryBase的其他一些实现。

由于“hacked”方法应该在绝大多数时间都有效,也许可以先通过在实体名称后面添加
id
来尝试“hacked”方法。如果失败,则检索实体元数据以获取primaryId

主键由CRM在创建实体时设置,格式为“实体名称”+“id”

如果您对此不满意,我将使用元数据服务一次性批量检索详细信息

RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest()
{
    EntityFilters = EntityFilters.Entity,
    RetrieveAsIfPublished = true
};

RetrieveAllEntitiesResponse response = (RetrieveAllEntitiesResponse)_serviceProxy.Execute(request);

foreach (EntityMetadata currentEntity in response.EntityMetadata)
{
    currentEntity.PrimaryIdAttribute
}
我不太清楚这样做的目的是什么,假设您正在为每个实体进行多个服务调用,一个额外的元数据调用不会有什么坏处。至于期望服务器“只知道”这些信息;无论如何,它可能必须查询元数据表


最后,如果有人必须向您提供实体名称,您也可以要求提供主键字段。

也许吧,但出于谨慎,我需要说“不”。我正在进行一个集成,没有什么可以阻止第三方用户(草率地)创建自定义实体(我需要能够处理这些实体),这些实体在理论上可能具有以模式“entityName+id”命名的属性,而实际上不是主实体属性。我不能冒那个错误的风险。谢谢,说得好。如果要将其推出,对于开箱即用的实体,可以确保“logicalName”+“id”不会是自定义字段。因此,对于不包含“u2;”或以“msdyn”开头的实体,被黑客攻击的方法通常是安全的。也就是说,当我遇到类似问题时,我也不情愿地得出结论,检索元数据是一条可行之路。这太令人沮丧了,因为当服务器在执行查询的上下文中时,它当然知道(或者很容易知道)主键。我认为不可能手动创建带有“entityName+id”的字段格式(当您创建实体时D365会自动创建它),所以如果您附加“id”,我会说您是安全的。如果您仍然不想使用此路径,我会查询元数据并将其保存在缓存中,以避免每次都有额外的服务调用
    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));
    }
RetrieveAllEntitiesRequest request = new RetrieveAllEntitiesRequest()
{
    EntityFilters = EntityFilters.Entity,
    RetrieveAsIfPublished = true
};

RetrieveAllEntitiesResponse response = (RetrieveAllEntitiesResponse)_serviceProxy.Execute(request);

foreach (EntityMetadata currentEntity in response.EntityMetadata)
{
    currentEntity.PrimaryIdAttribute
}