CRM QueryExpression with Link to Same Table / Entity - dynamics-crm

I am trying to perform the following SQL equivalent query within CRM using a QueryExpression and LinkEntity. Any ideas? I am fairly stumped. I have used the LinkEntity before but not sure how to reference or alias the same entity type.
select t1.UoMId, t1.BaseUoM, t1.UoMScheduleId, t1.Name, t1.Quantity
from UoMBase t1
inner join UoMBase t2 on t1.UoMScheduleId = t2.UoMScheduleId
where t2.UoMId = '57E59AB7-AC8F-E511-80F0-005056BE36DF';
Which will result in the following entity records:

Try to convert following to QueryExpression:
<fetch mapping="logical" version="1.0">
<entity name="UoM">
<attribute name="UoMId" />
<attribute name="BaseUoM" />
<attribute name="UoMScheduleId" />
<attribute name="Name" />
<attribute name="Quantity" />
<link-entity name="UoM" from="UoMScheduleId" to="UoMScheduleId" alias="t2" link-type="inner">
<filter>
<condition attribute="UoMId" operator="eq" value="57E59AB7-AC8F-E511-80F0-005056BE36DF" />
</filter>
</link-entity>
</entity>
</fetch>
QueryExpression query = new QueryExpression("uom");
query.ColumnSet = new ColumnSet(new[] { "uomid", "baseuom", "uomscheduleid", "name", "quantity", });
query.LinkEntities.Add(new LinkEntity("uom", "uom", "uomscheduleid", "uomscheduleid", JoinOperator.Inner) { EntityAlias = "t2" });
query.Criteria.AddCondition("t2", "uomid", ConditionOperator.Equal, guidID);
EntityCollection result = OrganizationService.RetrieveMultiple(query);

Related

Fetch XML returns 0 records where there is no related field

I'm using FetchXML to retrieve some field values for a few given IDs. The problem is that if I request a related field, and that field does not have a value, no records are returned.
For example, in using the following FetchXML, the Accounts for the given IDs do exist but since they DO NOT have a ParentAccount no values are returned.
<fetch mapping="logical">
<entity name="account">
<attribute name="name" />
<attribute name="ownerid" />
<link-entity name="account" to="parentaccountid" alias="parentaccountid">
<attribute name="name" />
</link-entity>
<filter>
<condition attribute="accountid" operator="in">
<value>9c8539fd-f7b1-e811-a973-000d3af4a510</value>
<value>be76ea1b-f8b1-e811-a973-000d3af4a510</value>
<value>1e76ea1b-f8b1-e811-a973-000d3af4a510</value>
<value>50843103-f8b1-e811-a973-000d3af4a510</value>
<value>b983ea1b-f8b1-e811-a973-000d3af4a510</value>
</condition>
</filter>
</entity>
</fetch>
Is there something I need to add to the link-entity to indicate that if it is null to still return the rest of the values?
You can mention join to be an outer if that field will be null for some records.
<link-entity name="account" to="parentaccountid" alias="parentaccountid" link-type="outer">
Read more

Select a count of contacts from accounts using FetchXML

Does anyone know the FetchXML format in order to select the count of contacts for accounts?
For example, I would have a list of AccountID's that I would us an IN filter for and I would just require the AccountID and the integer count of the contacts for that account.
Solved (see below) with a minor change to group by accounts. Here is the final fetchxml that I used:
<fetch xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" aggregate="true" distinct="false" mapping="logical">
<entity name="contact">
<attribute name="contactid" alias="recordcount" aggregate="count" />
<link-entity name="account" to="accountid" alias="accountid">
<attribute name="accountid" alias="accountid" groupby="true" />
<filter>
<condition attribute="accountid" operator="in">
<value>708039fd-f7b1-e811-a973-000d3af4a510</value>
<value>0a8139fd-f7b1-e811-a973-000d3af4a510</value>
<value>428139fd-f7b1-e811-a973-000d3af4a510</value>
<value>4a8139fd-f7b1-e811-a973-000d3af4a510</value>
<value>618139fd-f7b1-e811-a973-000d3af4a510</value>
<value>9f8139fd-f7b1-e811-a973-000d3af4a510</value>
<value>ae8239fd-f7b1-e811-a973-000d3af4a510</value>
</condition>
</filter>
</link-entity>
</entity>
</fetch>
You can do an aggregate fetch with a group by on the parentcustomerid.
<fetch distinct='false' mapping='logical' aggregate='true'>
<entity name='contact'>
<attribute name='contactid' alias='contact_count' aggregate='countcolumn' />
<attribute name='parentcustomerid' alias='parentcustomerid' groupby='true' />
<link-entity name='account' from='accountid' to='parentcustomerid'>
<filter type='and'>
<condition attribute='accountid' operator='in'>
<value>{00000000-0000-0000-0000-000000000001}</value>
<value>{00000000-0000-0000-0000-000000000002}</value>
</condition >
</filter>
</link-entity>
</entity>
</fetch>
This is straight forward when you use Rollup field.
Then you can query the count easily.
<fetch>
<entity name="account" >
<attribute name="name" />
<attribute name="new_contactcountrollup" />
</entity>
</fetch>
Update:
Why I said subquery is not supported in fetchxml since I was thinking the second solution.
--using just JOIN
SELECT a.accountid, count(1) AS [contact count] FROM contact c
INNER JOIN account a
ON c.parentcustomerid = a.accountid
WHERE a.accountid IN (
'{0ACDC4F5-4885-E811-A967-000D3A1A9407}', '{BA41CEBA-199F-E811-A96B-000D3A1A9EFB}')
GROUP BY a.accountid
--using SUBQUERY
SELECT a.accountid,
(SELECT Count(1) FROM contact c WHERE c.parentcustomerid = a.accountid) AS [contact count]
FROM account a
WHERE a.accountid IN (
'{0ACDC4F5-4885-E811-A967-000D3A1A9407}', '{BA41CEBA-199F-E811-A96B-000D3A1A9EFB}')

Not able to fetch "Name" of lookup fields of Link-Entity (Web API + FetchXml)

I have some fetchXml that I am executing through the Dynamics CRM Web API. THe fetchXml query is constructed like so:
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="new_someEntityA">
<attribute name="new_lookupForSomeEntityA" />
<link-entity alias="new_someEntityB" name="new_someEntityB" from="entityBId" to="entityAId" visible="false" link-type="outer">
<attribute name="new_lookupForSomeEntityB" />
</link-entity>
</entity>
</fetch>
When I send this query through the Web API, I get a response and the value for "new_lookupForSomeEntityA" includes the value (GUID) and a Formatted Value (it's name). But the response for "new_lookupForSomeEntityB" includes just the GUID and I can't find a way to get it's GUID and value. I've added a header record for:
"Prefer": "odata.include-annotations=OData.Community.Display.V1.FormattedValue"
but that appears to just get me formatted values for the primary entity and not the link entity. Is this a limitation of the Web API or am I doing something wrong? Any help would be appreciated.
Here is some code that returns formatted values for link-entity option sets with Web API + FetchXml. Tested against version 8.2 of the API:
var oDataUrl = 'https://[your_org].crm4.dynamics.com/api/data/v8.2/';
var encodedFetchXml = encodeURI(`
<fetch top="10" no-lock="true" >
<entity name="contact" >
<attribute name="fullname" alias="contactName" />
<link-entity name="incident" from="customerid" to="contactid" link-type="inner" alias="incident" >
<attribute name="caseorigincode" alias="incidentOrigin" />
</link-entity>
</entity>
</fetch>
`);
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: `${oDataUrl}contacts?fetchXml=${encodedFetchXml}`,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json");
XMLHttpRequest.setRequestHeader("Prefer", "odata.include-annotations=OData.Community.Display.V1.FormattedValue");
}
}).then(function (response) {
// formatted value included in the response objects
// incidentOrigin#OData.Community.Display.V1.FormattedValue:"WhatsApp"
console.dir(response);
});
This is the data that is returned:
{
"#odata.context":"https://[your_org].crm4.dynamics.com/api/data/v8.2/$metadata#contacts(contactid)",
"value":[{
"#odata.etag": "W/\"873006\"",
"contactid": "ecfd1feb-d826-468a-bfe3-6ebd781c39f4",
"contactName": "Ada Lovelace",
"incidentOrigin#OData.Community.Display.V1.FormattedValue": "WhatsApp",
"incidentOrigin": 269420000
}]
}
It works with both inner and outer link-types.
Link-Entity attribute alias named the same as the attribute
If you make the alias for a linked-entity attribute the same as the attribute name, then the attribute is not returned at all. This problem appears to be for all link-entity attributes.
<fetch top="500" no-lock="true" >
<entity name="contact" >
<attribute name="fullname" alias="contactName" />
<link-entity name="incident" from="customerid" to="contactid" link-type="inner" alias="incident" >
<attribute name="caseorigincode" alias="caseorigincode" />
</link-entity>
</entity>
</fetch>
Leaving out the link-entity attribute alias
If you leave out the alias for a linked-entity attribute, it is returned with a horrible name:
<fetch top="500" no-lock="true" >
<entity name="contact" >
<attribute name="fullname" alias="contactName" />
<link-entity name="incident" from="customerid" to="contactid" link-type="inner" alias="incident" >
<attribute name="caseorigincode" />
</link-entity>
</entity>
</fetch>
The returned objects have a field like this:
incident_x002e_caseorigincode#OData.Community.Display.V1.FormattedValue:"WhatsApp"
Maybe the issue you experienced was resolved in version 8.2.

FetchXml query generates a 'Generic SQL Error' but works if I switch the linked entities around?

I'm attempting to query the product catalog of a "vanilla" CRM 2015, my final aim is to retrieve the active products by price list and substring of name, at the moment I'm hard-coding my data as follows:
PriceLevel: hardcoded GUID
Name: hardcoded "a"
The resulting XML is this:
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true" count="50">
<entity name="productpricelevel" >
<attribute name="uomid" />
<filter type="and">
<condition attribute="pricelevelid" operator="eq" uitype="pricelevel" value="{7080964d-85df-e411-80ba-00155d0b0c38}" />
</filter>
<link-entity name="product" from="productid" to="productid" alias="ac" >
<attribute name="name" />
<attribute name="productnumber" />
<order attribute="productnumber" descending="false" />
<filter type="and">
<condition attribute="name" operator="like" value="a" />
<condition attribute="statecode" operator="eq" value="0" />
</filter>
</link-entity>
</entity>
</fetch>
When I attempted to execute the query, I got Generic SQL Error. I then looked at the trace logs, and found this:
Exception when executing query: select DISTINCT "productpricelevel0".UoMId as "uomid", "productpricelevel0".UoMIdName as "uomidname",
coalesce("LL0".Label,"ac".Name ) as "ac.name", "ac".ProductNumber as "ac.productnumber"
from ProductPriceLevel as "productpricelevel0" join Product as "ac"
on ("productpricelevel0".ProductId = "ac".ProductId and ( coalesce("LL0".Label,"ac".Name) like 'a' and "ac".StateCode = 0))
left outer join BusinessDataLocalizedLabel as "LL0" on ("LL0".ObjectId = "ac".ProductId and "LL0".LanguageId = 1033 and "LL0".ObjectColumnNumber = 6 )
where ("productpricelevel0".PriceLevelId = '7080964d-85df-e411-80ba-00155d0b0c38') order by
"ac".ProductNumber asc
Exception: System.Data.SqlClient.SqlException (0x80131904): The multi-part identifier "LL0.Label" could not be bound
In an attempt to identify a pattern, I switched the JOIN around, ending up with this XML:
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true" count="50" >
<entity name="product" >
<attribute name="name" />
<attribute name="productnumber" />
<order attribute="productnumber" descending="false" />
<filter type="and" >
<condition attribute="name" operator="like" value="a" />
<condition attribute="statecode" operator="eq" value="0" />
</filter>
<link-entity name="productpricelevel" from="productid" to="productid" alias="ac" >
<attribute name="uomid" />
<filter type="and" >
<condition attribute="pricelevelid" operator="eq" uitype="pricelevel" value="{7080964d-85df-e411-80ba-00155d0b0c38}" />
</filter>
</link-entity>
</entity>
</fetch>
This time, I got my results as expected, no errors.
The organization is new and only contains Sitemap/HTML/JS customizations (the entities I'm querying are not customized yet), 1033 is the base language, there is another language installed and enabled but it isn't used by any of the 2 users of the system.
What's going on in the first case ?
UPDATE: The first query works against a 2013 organization. This is starting to feel like a bug.
This definitely is a bug. I guess Microsoft changed the engine that converts QueryBase queries into T-SQL.
This week we had an issue with linked entities. It was about the following condition:
.AddCondition("statuscode", ConditionOperator.In, new object[] { 1, 2, 3 });
When applied on the primary entity of a QueryExpression, the condition is processed as expected. When applied on a linked entity it fails. In previous versions of Dynamics CRM it works in both scenarios.

Left join in FetchXml?

How do i do a left join using FetchXml?
Consider a simple SQL query like the following:
select person.name, address.city from person
left join address on person.addressid = address.addressid
How would something simple like this be done using FetchXml?
Currently my FetchXml query looks like the following:
<fetch mapping='logical'>
<entity name='person'>
<attribute name='name' />
<link-entity name='address' from='addressid' to='addressid'>
<attribute name='city' />
</link-entity>
</entity>
</fetch>
Update your <link-entity> like so:
<link-entity name='address' from='addressid' to='addressid' link-type='outer'>

Resources