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

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>

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>

How to filter using fetch to get accurate results?

I need to get all accounts that have phonecalls in state not open, so I created a query on fetch and got some results.
After checking my results I found that I got all accounts that have minimum 1 phonecall that was not open, but I need to get the accounts that all of their connected phonecalls are not open (can't have even 1 in open state) is it possible to do by fetch ?
** by NOT OPEN I mean state of Canceled or Completed.
Here is my fetch query:
#"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'>
<entity name='account'>
<attribute name='name' />
<order attribute='accountamount' descending='true' />
<link-entity name='phonecall' from='regardingobjectid' to='accountid' alias='ab'>
<filter type='and'>
<condition attribute='statecode' operator='ne' value='0' />
</filter>
</link-entity>
</entity>
</fetch>";
What you are looking for is Unmatch query. This can be achieved in 2 queries using fetchxml.
First Query: You have to pull all the Accounts with open phonecalls.
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="true" >
<entity name="account" >
<attribute name="accountid" />
<order attribute="accountamount" descending="true" />
<link-entity name="phonecall" from="regardingobjectid" to="accountid" alias="ab" >
<filter type="and" >
<condition attribute="statecode" operator="eq" value="0" />
</filter>
</link-entity>
</entity>
</fetch>
Second Query: Iterate & pass the first query Account resultset as <value> like below, to filter out them.
<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" />
<filter type="and" >
<condition attribute="accountid" operator="not-in" >
<value><GUID of ACCOUNT1 with OPEN PHONECALL></value>
<value><GUID of ACCOUNT2 with OPEN PHONECALL></value>
<value><GUID of ACCOUNT3 with OPEN PHONECALL></value>
</condition>
</filter>
</entity>
</fetch>
Read for idea

CRM retrieve records with Fetchxml on today minus n days

I need fetchxml condition operator to retrieve all my appointments on today-11 days. I mean if I run my query today(12/04/2018) I want to retrieve my created records on 01/04/2018. If I run on 13/04/2018 - records created on 02/04/2018. Which operator can I use to get what I need?
<fetch distinct="false" mapping="logical" output-format="xml-platform" version="1.0">
<entity name="appointment">
<attribute name="subject"/>
<attribute name="statecode"/>
<attribute name="scheduledstart"/>
<attribute name="scheduledend"/>
<attribute name="createdby"/>
<attribute name="regardingobjectid"/>
<attribute name="activityid"/>
<attribute name="instancetypecode"/>
<order descending="false" attribute="subject"/>
<filter type="and">
<condition attribute="createdon" value="" operator=""/>
</filter>
</entity>
There is no single operator, but you can easily combine two:
<filter type="and">
<condition attribute="createdon" operator="last-x-days" value="11" />
<condition attribute="createdon" operator="olderthan-x-days" value="10" />
</filter>
There is no straight operator for this. You have to use eq operator & calculate the expression (-11) yourself if you are using this fetchxml query in SSRS report #date:
<condition attribute="new_date" operator="eq" value="#date"></condition>
Or calculate in javascript/C# & pass it to paramDate, if you are calling this in form script or server code:
'<condition attribute="new_date" operator="eq" value="' + paramDate + '"></condition>'

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