使用FetchXML获取(强类型)相关实体

本文关键字:实体 强类型 FetchXML 获取 使用 | 更新日期: 2023-09-27 17:49:01

我使用fetchXML来连接两个实体,并且只能获得第一个列表的结果。我可能犯了一个愚蠢的错误,但这让我浪费了几个小时。

var query = @"
  <fetch version='1.0' mapping='logical' distinct='true'>
  <entity name='contact'>
    <all-attributes />
    <link-entity name='new_custom' from='new_contactid' to='contactid' link-type='inner'>
      <all-attributes />
    </link-entity>
  </entity>
</fetch>
";
var fe = new FetchExpression(query);
var result = service.RetrieveMultiple(fe);
// This contact entity is properly filled
var contact = result.Entities.First().Cast<Contact>();
// This relationship is null, that's unexpected!
var custom = contact.new_contact_new_custom;
// Also null (not sure if this should work)
var related = contact.GetRelatedEntity<new_custom>("new_contact_new_custom", null);

我确实看到在Contact实体的AttributesFormattedValues属性中检索了正确的数据。但为什么这种关系不能正确建立呢?如何将这些数据转换为正确的"自定义"实体类型?

使用FetchXML获取(强类型)相关实体

第一:您确定您的查询返回早期绑定对象吗?在下面的例子中,我假设您获得了Entity对象(晚绑定),但是对于这个例子来说,这并没有太大的区别。

查询的响应基本上是您请求的类型的实体对象的普通表,在本例中为"contact"。连接实体的字段也可以添加到这个表中,但是它们被包装在AliasedValue对象中。它们的列名以LinkEntity别名作为前缀,以防止名称冲突。

您的var contact = result.Entities.Cast<Contact>();行表明变量contactContact类型,但它实际上是IEnumerable<Contact>。(使用var并不总是那么有用。)由于这个原因,我怀疑您的最后两行甚至不能编译。

在下面的示例中,向组织发送一个获取查询。svc端点。(注意alias属性。)然后从查询结果集的第一行获取实体"new_custom"的字段"new_name"。

var fetchXml = @"
    <fetch version='1.0' mapping='logical' distinct='true'>
        <entity name='contact'>
        <all-attributes />
        <link-entity name='new_custom' alias='nc' from='new_contactid' to='contactid' link-type='inner'>
            <all-attributes />
        </link-entity>
        </entity>
    </fetch>
";
var query = new FetchExpression(fetchXml);
var response = service.RetrieveMultiple(query);
var contact = response.Entities[0];
var customField = contact.GetAttributeValue<AliasedValue>("nc.new_name");
string name = customField != null ? (string)customField.Value : null;

这个回答有点晚了,但是这个问题帮助我找到了正确的方向,所以我想我应该添加我的部分。正如Henk在他的回答的评论中所说,您可以实现一个相对简单的扩展方法,将链接实体的字段解析为另一个实体,然后将其转换为早期绑定类型。您只需要知道用于link-entity元素的别名。这是我的实现(编辑:添加的FormattedValues):

    public static T ToRelatedEntity<T>(this Entity rawEntity, string relatedAlias)
        where T:CrmEntity, new() 
        //CrmEntity is a base class I insert into my generated code 
        //to differentiate early-bound classes; you can use Entity
    {
        var result = new Entity(new T().LogicalName);
        foreach(var attribute in rawEntity.Attributes
                                    .Where(kvp=>kvp.Key
                                              .StartsWith(relatedAlias + ".")))
        {
            var newName = attribute.Key.Replace(relatedAlias + ".", String.Empty);
            result[newName] = ((AliasedValue)attribute.Value).Value;
        }
        foreach(var formattedValue in rawEntity.FormattedValues
                                        .Where(kvp=>kvp.Key
                                                  .StartsWith(relatedAlias + ".")))
        {
            var newName = formattedValue.Key.Replace(relatedAlias + ".", String.Empty);
            result.FormattedValues[newName] = formattedValue.Value;
        }
        return result.ToEntity<T>();
    }
//usage
var query = new FetchExpression(fetchXml);
var response = service.RetrieveMultiple(query);
var contact = response.Entities[0].ToEntity<Contact>();
var newCustom = response.Entities[0].ToRelatedEntity<new_custom>("nc");

非常基本,但它似乎工作得相当好,只要你没有混叠任何字段你检索,你检索足够的信息来填充对象的有效实例(Id,主字段等)。这比尝试用初始化器实例化相关对象要好得多(特别是因为许多字段,如StateCode是只读的)。