Fetch XML returns 0 records where there is no related field - dynamics-crm

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

Related

How to pass null or empty to FetchXML filters?

Scenario: I've a text field in Dynamics CRM on Order Type. This field is integrated with some other systems and it'll be accepting only already stated list of values; like, ABC, IJK, XYZ etc. Now I can query this field using Advanced find if it contain data or not.
Now in report, I've a parameter that is having all those possible value and one additional as "Does not contain data" and its value is empty string. I've also enabled this report parameter for multi-select. But I am unable to get the orders if any of the value is selected from report parameters.
Below is my FetchXML query, Please let me know what I am missing in below.
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="invoicedetail">
<attribute name="productid" />
<attribute name="invoicedetailid" />
<attribute name="tv_ordertype" />
<order attribute="productid" descending="false" />
<filter type="and">
<condition attribute="tv_ordertype" operator="in" value="#Order_Types" />
</filter>
</entity>
</fetch>
Unfortunately you cannot combine the values ("ABC", "IJK", "XYZ") with an empty string option. Think about how SSRS will parse the empty string into FetchXml:
<condition attribute="tv_ordertype" operator="in" value="" />
Because the in operator has an empty string, there will be no matching results.
One approach that might work is to change your FetchXml to use an or filter, like this
<filter type="or">
<condition attribute="tv_ordertype" operator="null" />
<condition attribute="tv_ordertype" operator="in" value="#Order_Types" />
</filter>
This will now return all values from CRM that match your criteria OR have a null tv_ordertype
Then you can apply additional filtering at the tablix / report level
Try something like below
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="invoicedetail">
<attribute name="productid" />
<attribute name="invoicedetailid" />
<attribute name="tv_ordertype" />
<order attribute="productid" descending="false" />
<filter type='and'>
<condition attribute="tv_ordertype" operator="in" value="#Order_Types" />
</filter>
</entity>
</fetch>
Your fetch XML should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="invoicedetail">
<attribute name="productid" />
<attribute name="invoicedetailid" />
<attribute name="tv_ordertype" />
<order attribute="productid" descending="false" />
<filter type="and">
<condition attribute="tv_ordertype" operator="in"/>
<value>#Order_Types[0]</value>
<value>#Order_Types[1]</value>
<!-- etc -->
</condition>
</filter>
</entity>
</fetch>

FetchXML - Find records not linked to specific record via N:N

There are numerous posts for finding "not-in" to find records of type a that have no associations to record type b.
I want to extend this in my scenario I have a Database record type and a Server Upgrade record type with an N:N between them. (there is an N:N between database and server but that's not part of this query)
I want to find all database records that are not already linked to the specific server upgrade I am working on. My attempts are failing because the database can be linked to other server upgrade records
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true" >
<entity name="dsg_databases" >
<attribute name="dsg_databasesid" />
<filter type="and" >
<condition entityname="ae" attribute="dsg_serverupgradeid" operator="neq" value="25dbe565-f435-e911-a976-000d3a2bcd97" />
</filter>
<link-entity name="dsg_dsg_serverupgrade_dsg_databases" from="dsg_databasesid" to="dsg_databasesid" link-type="outer" intersect="true" >
<link-entity name="dsg_serverupgrade" from="dsg_serverupgradeid" to="dsg_serverupgradeid" link-type="outer" alias="ae" />
</link-entity>
</entity>
</fetch>
The reason being, in a plugin I then associate these databases to the server upgrade record but get an error Cannot insert duplicate key if they are already linked.
For reference and in case there's a better way, I take the entity collection returned by the FetchXML, convert to an EntityReferenceCollection ercDatabases and use service.Associate(targetEntity.LogicalName, targetEntity.Id, relationship, ercDatabases);
Edit - I'm trying to avoid cycling through each database record returned and checking whether they're associated. I'd rather do it in the single query for performance.
Moving the filter condition of the recordid you're trying to exclude to the intersect entity (ensuring it's an outer join) and ignoring the second join to the actual server upgrade record, then having a condition in the main entity filter pointing to the join record checking for null appears to work
<fetch top="50" >
<entity name="dsg_databases" >
<attribute name="dsg_databasesid" />
<attribute name="dsg_name" />
<filter type="and" >
<condition entityname="ae" attribute="dsg_serverupgradeid" operator="null" />
</filter>
<link-entity name="dsg_dsg_databases_dsg_server" from="dsg_databasesid" to="dsg_databasesid" visible="false" intersect="true" >
<link-entity name="dsg_server" from="dsg_serverid" to="dsg_serverid" alias="ad" >
<filter type="and" >
<condition attribute="dsg_serverid" operator="eq" value="98f46447-7f7b-e811-a95a-000d3a22cba0" />
</filter>
</link-entity>
</link-entity>
<link-entity name="dsg_dsg_serverupgrade_dsg_databases" from="dsg_databasesid" to="dsg_databasesid" link-type="outer" intersect="true" alias="ae" >
<filter type="and" >
<condition attribute="dsg_serverupgradeid" operator="eq" value="25dbe565-f435-e911-a976-000d3a2bcd97" />
</filter>
</link-entity>
</entity>
</fetch>

fetchXml from CRM - is it possible to fetch just the "last" record for a linked entity?

I tried using top="1" and an order descending in the linked-entity element, and I still get back multiple records joined.
<fetch version="1.0" mapping="logical" >
<entity name="x" >
<attribute name="xid" />
<link-entity alias="d" top="1" name="t" from="xid" to="xid" link-type="outer">
...
<order attribute="xdate" descending="true" />
</link-entity>
</entity>
</fetch>
You can't limit the number of link entities returned. What you could do instead is make link-entity d the entity and entity x the link-entity so you can use top as it is intended.

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.

Can you write a single FetchXML query to get 1:many relationship?

Is it possible to write a single FetchXML query that gets a root entity and multiple children? All I've been able to do is 1:1.
James Wood is correct. Fetch XML is recursive so by using the link entity you can get the information you want.
For example, the following is valid:
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true">
<entity name="account">
<attribute name="name" />
<attribute name="primarycontactid" />
<attribute name="telephone1" />
<attribute name="accountid" />
<order attribute="name" descending="false" />
<link-entity name="contact" from="parentcustomerid" to="accountid" alias="aj">
<attribute name="firstname" />
<attribute name="lastname" />
<attribute name="telephone1" />
<link-entity name="businessunit" from="businessunitid" to="owningbusinessunit" alias="ak">
<attribute name="name" />
<attribute name="address1_line1" />
<attribute name="address1_line2" />
<attribute name="address1_line3" />
<filter type="and">
<condition attribute="name" operator="not-null" />
</filter>
</link-entity>
</link-entity>
</entity>
</fetch>
If your question really is "Is it possible to write a single FetchXML query that gets a SINGLE root entity and multiple children" then the answer is unfortunately no. However if you are able to handle duplicates of root data (For example using the Grouping functionality of an SSRS report) then what you require is entirely possible
Unless I've misunderstood the question this is very possible.
So for example you want to find all the contacts related to a given account. This is represented in Crm by the Parent Customer Lookup on the contact to the account.
<fetch mapping="logical" count="100" version="1.0">
<entity name="account">
<attribute name="name" />
<link-entity name="contact" from="parentcustomerid" to="accountid">
<attribute name="fullname" />
</link-entity>
</entity>
</fetch>
Which gives you a result set that looks like this:
<resultset morerecords="0" paging-cookie="<cookie page="1"><accountid last="{E704FAD6-2D4B-E111-9FED-00155D828444}" first="{AD912122-6B3C-E111-9B37-00155D828444}" /></cookie>">
<result>
<name>RGD Mining Inc</name>
<accountid>{E704FAD6-2D4B-E111-9FED-00155D828444}</accountid>
<accountid.fullname>Bill Miner</accountid.fullname>
</result>
<result>
<name>RGD Mining Inc</name>
<accountid>{E704FAD6-2D4B-E111-9FED-00155D828444}</accountid>
<accountid.fullname>Green</accountid.fullname>
</result>
</resultset>
No, it is not possible.
I'm happy to report that it is possible. I have a solution that worked well for me.
The only caveat is that if you have multiple child accounts you will get multiple results for the parent. For example:
parent 1: child 1
parent 2: child 1
parent 2: child 2
This means that you would then have to run the results through a sorting function, to get either all the children under parents in a multi dimensional array, or get all the accounts as unique entries in a flat array.
Also, this only goes down one level. If your hierarchy is multi-level, this code would need to be modified.
<fetch distinct="false" mapping="logical">
<entity name="account">
<attribute name="name" />
<link-entity name="account" alias="childaccount" to="accountid" from="parentaccountid" link-type="outer">
<attribute name="name" alias="childname" />
</link-entity>
</entity>
</fetch>

Resources