Simplifying FetchXml: Unaliasing Entity Attributes in Complex Queries
FetchXml is a powerful query language used by developers to fetch data from the Microsoft Dynamics 365 suite. While it provides flexibility and robustness with features like joins and filtering, working with aliased attributes can sometimes be challenging. This post seeks to shed light on how to handle these aliased attributes more effectively.
The challenge
When you perform joins in FetchXml, it's necessary to assign an alias to the new table (or entity) you're joining with. This ensures that columns from the two tables won't collide even if they share the same name. As you navigate through the result set, this aliasing allows you to easily move from parent to child records. However, the challenge arises when trying to extract values from these aliased columns, as the object model doesn't always make it straightforward. Consider the following fictitious FetchXml query:
<fetch top='50'>
<entity name='parent'>
<!-- some attributes here-->
<filter>
<condition attribute='name' operator='eq' value='{name}' />
</filter>
<link-entity name='child' from='child_parentid' to='parentid' link-type='outer' alias='child'>
<!--some attributes here-->
<filter>
<condition attribute='child_contactid' operator='eq' value='contactId' uitype='contact' />
</filter>
</link-entity>
</entity>
</fetch>
It's essential not to hardcode values in FetchXml queries. Instead, utilize string interpolation (i.e., $"..." syntax), constants, and variables for more flexibility and maintainability.
When iterating over the result of the above query, one often ends up with a pattern similar to:
var aliasedvalue = entity.GetAttributeValue<AliasedValue>(fieldname);
var value = aliasedvalue.Value;
This necessitates null checks, considering default values, and can get quite tedious.
The solution
public static T GetAliasedValue<T>(this Entity entity, string valueField)
{
var aliasedvalue= entity.GetAttributeValue<AliasedValue>(valueField);
return attribute != null ? (T)attribute.Value : default(T);
}
However, a drawback is that you need to know the aliased name of each field beforehand. So, how do we simplify this for most scenarios, especially when only the values are desired?
For this, I introduce the Unalias
method. It unaliases a given entity without requiring knowledge of the alias name. Adjust this method according to your specific use cases:
public static class EntityExtensions
{
public static Entity Unalias(this Entity entity)
=> entity?.Attributes.FirstOrDefault().Value is not AliasedValue firstAttribute ? entity : entity.Attributes.Aggregate(
new Entity(firstAttribute.EntityLogicalName),
(e, kv) =>
{
if (kv.Value is AliasedValue aliased)
{
e.Attributes.Add(aliased.AttributeLogicalName, aliased.Value);
}
else
{
// Do something with non-aliased attributes if required.
}
return e;
});
}
Conclusion
Working with FetchXml brings its own set of complexities, especially when dealing with aliased attributes. By utilizing the above approaches, developers can streamline their code, making it more readable and maintainable.
For more in-depth exploration of FetchXml and related topics, here.