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

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>

Related

How to fetch users not in a specific queue/team?

I have a task to create a custom grid view of users not in a specific team.
I created the fetch according to team (entity) not equal to my specific team but I didn't get the wanted results after recheck I changed it from team to Queue and still no good results, is there an option to get the needed results using Fetch
In Dynamics 2016 you cannot do this using FetchXml.
In Dynamics 365 this is possible. It would look like this:
<fetch attribute="teamid" operator="eq" value="00000000-0000-0000-0000-000000000000" >
<entity name="systemuser" >
<attribute name="fullname" />
<filter>
<condition entityname="teammembership" attribute="teamid" operator="null" />
</filter>
<link-entity name="teammembership" from="systemuserid" to="systemuserid" link-type="outer" >
<attribute name="teamid" />
<filter>
<condition attribute="teamid" operator="eq" value="4212a8d9-4893-eb11-b1ac-000d3adb2ab1" />
</filter>
</link-entity>
</entity>
</fetch>
The condition doing the trick here is <condition entityname="teammembership" attribute="teamid" operator="null" />, where you specify the entity that is the right part in the left outer join.
As said, you cannot do this in Dynamics 2016, so you have no other option than executing the query above without its first filter and do the filtering on the resultset returned by the query.

How to query a keyword on different attributes based on entity in fetchXML?

I have 2 entities in the database; an Appointment and an Email. I want to write a search function that fetches all Appointments and Emails that contains a string a user enters. However, I want to search on different attributes based on which entity it is. For instance: I want to fetch all Appointments that have the attribute subject containing the string "meeting today" and I also want to fetch all Emails that have the attribute description containing the same string. So in simple terms, only search the subject line for Appointments and only search descriptions for Emails.
Here's what my fetchXml looks so far:
<fetch count="10" distinct="true" mapping="logical" no-lock="true" output-format="xml-platform" page="1" returntotalrecordcount="false" version="1.0">
<entity name="activitypointer">
<attribute name="subject"/>
<attribute name="description"/>
<attribute name="activitytypecode"/>
<filter type="or">
<condition attribute="activitytypecode" operator="like">
<value>Email</value>
</condition>
<filter type="and">
<condition attribute="description" operator="like" value="%meeting today%"/>
</filter>
</filter>
<filter type="or">
<condition attribute="activitytypecode" operator="like">
<value>Appointment</value>
</condition>
<filter type="and">
<condition attribute="subject" operator="like" value="%meeting today%"/>
</filter>
</filter>
</entity>
</fetch>
This doesn't seem to grab any records back however. I can successfully fetch records when querying on a single entity type, but putting both filters doesn't return anything. Is what I'm asking possible to do in fetchXML? Or is there an issue with how I've constructed my query?
I just did a quick test in my environment, this is working. You can build such queries in Advanced find & download the fetchxml, before editing/testing in XrmToolBox FetchXml builder.
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" >
<entity name="activitypointer" >
<attribute name="activitytypecode" />
<attribute name="subject" />
<filter type="and" >
<filter type="or" >
<filter type="and" >
<condition attribute="activitytypecode" operator="eq" value="4202" />
<condition attribute="subject" operator="like" value="%test%" />
</filter>
<filter type="and" >
<condition attribute="activitytypecode" operator="eq" value="4201" />
<condition attribute="description" operator="like" value="%test%" />
</filter>
</filter>
</filter>
</entity>
</fetch>

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

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.

Resources