multiple joins in fetchxml involving more than 2 entities - dynamic

I have three entities
Case - new_welfarecases
Goal - new_casegoal
Activity - new_welfarecaseactivity
Now each Case will have multiple Goals and each Goal will have multiple Activities(N:1)
In the goal entity, new_caseid is the lookup field for Case
The case has a business process flow defined and the flow has stages like initiation, moved to next level etc
The stage of the goal is captured in field called new_startstageofthecase
To get list of goals for a case in particular stage I use the below fetchxml
var fetchXml = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>"
+"<entity name='new_casegoal'>"
+"<attribute name='new_startstageofthecase' />"
+"<filter type='and'>"
+"<condition attribute='new_startstageofthecase' operator='"+ goalFilterOption +"' value='" + currentStageId +"' />"
+"</filter>"
+"</entity>"
+ "</fetch>";
Subgrid.control.SetParameter("fetchXml", fetchXml); //set the fetch xml to the sub grid
Now I want to retrieve the list of activities for a case in particular stage, how can I fetch them?
Activities entity does not have the stage field, but it has to be fetched from the goal it is associated to.
The lookup for goal in activity entity is new_childwelfarecasegoalid

Everytime I need to build those queries I go to the Advanced Find in CRM.
1) Start with an advanced find to look for Activities.
2) Then add a join to Goal entity (Related Entities -> Goal),
3) Then, add a join from Goal to the Record entity.
You can add as many filters on each of the entities. In your case a filter for the specific Stage and Record.
Then export the resulting FetchXml from the View.

As I understand you, you want to:
Fetch Activities that have a Goal that has an Record.
The Record should be a specific Record.
The Record should have a specific stage in the BPF.
A query along those lines would look like:
<fetch version='1.0' mapping='logical' distinct='false'>
<entity name="new_Activity">
<all-attributes />
<link-entity name="new_Goal" from="new_goalid" to="new_goal">
<link-entity name="new_Record" from="new_recordid" to="new_record">
<filter type="and">
<condition attribute="new_recordid" operator="eq" value="{<record-guid-here>}" />
</filter>
<link-entity name="processstage" from="processstageid" to="stageid">
<filter type="and">
<condition attribute="stagename" operator="eq" value="<stage-name-here>" />
</filter>
</link-entity>
</link-entity>
</link-entity>
</entity>
</fetch>

Related

CRM Api FetchXml replaces characters when using like

I'm trying to call CRM Api to fetch contacts. The requirement says I can search by name using the LIKE operator.
I'm using the fetchxml below to query CRM:
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
<entity name="contact">
<attribute name="fullname" />
<filter type="and">
<condition attribute="statecode" operator="eq" value="0" />
</filter>
<filter type="and">
<condition attribute="fullname" operator="like" value="%ben%" />
</filter>
</entity>
</fetch>
The problem is: If I try with "test" for example, it works fine. But if I try to search for "ben" it doesn't. I believe the issue is related to encoding but I can't find a way to fix it. Any ideas?
Seems like encoding error in your code. Try to pass your encoded fetchxml query in the below url & test in the browser address bar. If it results the expected record(s) then it’s not platform problem.
https://<yourorg>.crm.dynamics.com/api/data/v8.2/contacts?fetchXml=encodedFetchXML
To use FetchXml, we need to format FetchXml in usable Web API service
endpoint format. We do this by storing the FetchXML in a variable and
encoding the string with the encodeURI function native to JavaScript as
below.
var encodedFetchXml = encodeURI(fetchContact);
Read more
Update:
I tested this. Both the below fetch filter worked & gave me the expected contact record in browser test.
<condition attribute="lastname" operator="like" value="%thiy%" />
<condition%20attribute="lastname"%20operator="like"%20value=%27%25thiy%25%27%20/>
Edit:
We faced this issue in our Production application today when users trying to search for %bernhard%, but we are handling in code with value="%%bbbernhard%" as a workaround.

FetchXML next page results

I want to populate a grid with data from Dynamics CRM. I use fetchXML, to get for each page 10 records. I want to get to the next page, to retrieve the next 10 records. But this isn't happening, I'm using XRMToolbox to simulate the fetch query but it returns me the same results, regardless of the page attribute value.
The fetchXML query is:
<fetch version="1.0" output-format="xml-platform" mapping="logical" count="10" page="1" aggregate="true" distinct="false" >
<entity name="webpage" >
<attribute name="url" groupby="true" alias="url" />
<attribute name="webpageid" aggregate="count" alias="top" />
<order descending="true" alias="top" />
</entity>
</fetch>
If I change the page attribute value, say to 10 the response won't be different.
Can anyone help me with this?
UPDATE
After many tests with XRMToolbox I've come to conclusion that this query won't listen, whatever page I provide to it. This is because of the aggregate attribute. If I remove it and of course remove the count aggregate, then changing the page attribute will actually fetch for me the next page results.
So in summary page attribute doesn't like the aggregate attribute. Maybe this can work with paging cookies, but I haven't tested it yet, I will test it and update this post.
To implement paging you need to use not only page number/records per page attributes but paging cookie as well. This msdn article provides all code you need to implement paging.

case statement inside of fetchxml script

Please note that although this question is an entirely different question, it relates directly to this question.
The following is the script that returns the dataset for my SSRS chart:
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false" aggregate="true">
<entity name="account">
<attribute name="bio_employeesworldwide" alias="TotalWorldWideEmployees" aggregate="sum" />
<filter>
<condition attribute="customertypecode" operator="eq" value="2" />
</filter>
<link-entity name="contact" from="parentcustomerid" to="accountid" alias="contact">
<attribute name="bio_webuseraccountstatus" alias="count_bio_webuseraccountstatus" aggregate="countcolumn" />
<attribute name="bio_webuseraccountstatus" alias="bio_webuseraccountstatusgroupby" groupby="true" />
</link-entity>
</entity>
</fetch>
The values for bio_webuseraccountstatus can be Active, Inactive, Disabled, Pending, etc..
In FetchXML is there a way to do a case statement where you "InActive" for every value that is not equal to "Active" ?
As you can see I've been trying to solve this issue within the reporting layer, but am experiencing lots of "string format" issues.
Can this be done with the dataset layer (fetchxml) instead?
According to this Microsoft forum post:
There's no equivalent function in FetchXml. Instead, you will need to return each field value, and process the CASE logic in the calling code. If this FetchXml is to be used in a report, then you may be able to implement the CASE logic in a calculated field on the report.
You can always parse the output of the fetchxml on return.
So rather than pushing to the screen, report, or db, the original record field of isreceivetravelalerts, you check the status (zero or one) and rewrite it, and add the new variable to your output. Clunky, but useful.
if ($record->isreceivetravelalerts == 1)
{
$travel_alerts = "Active";
}
$travel_alerts = "Inactive";

FetchXML nvarchar returns nothing - Custom Report for CRM

I am trying to get data from Dynamics CRM 2013 for a custom report using FetchXML.
I "converted" the following SQL Query to FetchXML using this page: http://www.sql2fetchxml.com/
SQL:
SELECT
accountidname,
billto_line1,
billto_postalcode,
billto_city,
invoicenumber,
name,
description
FROM FilteredInvoice
WHERE invoiceid = #invoiceid
FetchXML:
<fetch mapping="logical">
<entity name="invoice">
<attribute name="accountidname" />
<attribute name="billto_line1" />
<attribute name="billto_postalcode" />
<attribute name="billto_city" />
<attribute name="invoicenumber" />
<attribute name="name" />
<attribute name="description" />
<filter>
<condition attribute="invoiceid" operator="eq" value="#invoiceid" />
</filter>
</entity>
</fetch>
Both, "accountidname" and (e.g.) "billto_line1" are NVARCHAR(4000) and both contain data, but if I try to execute the query (e.g. in the "Query Designer" in Visual Studio) only the data of "billto_line1" is shown, not the data of "accountidname".
Since both fields "accountidname" and "billto_line1" are of the same type (nvarchar(4000)) and contain information in the database (I checked it with the "Microsoft SQL Server Management Studio") I am wondering why I can only receive the information from one of those two.
This has happend with many different fields of the type NVARCHAR - some are displayed correctly, while some are not - and I have no idea why.
I would be very pleased if somebody could give me a hint :)
Thank you
accountidname is on the Views, not the actual tables, in SQL. It is not a field on the invoice entity and therefore will not return any information in a FetchXml request.
You should be able to retrieve the Account's name by using accountid - I don't remember in SSRS how the Name property of an EntityReference is surfaced but it should be available.
The FetchXml converter is good at converting SQL SELECT's to FetchXml format and converting joins. It will not validate that the SQL fields are available in FetchXml - that could only be done by accessing the metadata of the CRM Org.

Quickest method for matching nested XML data against database table structure

I have an application which creates datarequests which can be quite complex. These need to be stored in the database as tables. An outline of a datarequest (as XML) would be...
<datarequest>
<datatask view="vw_ContractData" db="reporting" index="1">
<datefilter modifier="w0">
<filter index="1" datatype="d" column="Contract Date" param1="2009-10-19 12:00:00" param2="2012-09-27 12:00:00" daterange="" operation="Between" />
</datefilter>
<filters>
<alternation index="1">
<filter index="1" datatype="t" column="Department" param1="Stock" param2="" operation="Equals" />
</alternation>
<alternation index="2">
<filter index="1" datatype="t" column="Department" param1="HR" param2="" operation="Equals" />
</alternation>
</filters>
<series column="Turnaround" aggregate="avg" split="0" splitfield="" index="1">
<filters />
</series>
<series column="Requested 3" aggregate="avg" split="0" splitfield="" index="2">
<filters>
<alternation index="1">
<filter index="1" datatype="t" column="Worker" param1="Malcom" param2="" operation="Equals" />
</alternation>
</filters>
</series>
<series column="Requested 2" aggregate="avg" split="0" splitfield="" index="3">
<filters />
</series>
<series column="Reqested" aggregate="avg" split="0" splitfield="" index="4">
<filters />
</series>
</datatask>
</datarequest>
This encodes a datarequest comprising a daterange, main filters, series and series filters. Basically any element which has the index attribute can occur multiple times within its parent element - the exception to this being the filter within datefilter.
But the structure of this is kind of academic, the problem is more fundamental:
When a request comes through, XML like this is sent to SQLServer as a parameter to a stored proc. This XML is shredded into a de-normalised table and then written iteratively to normalised tables such as tblDataRequest (DataRequestID PK), tblDataTask, tblFilter, tblSeries. This is fine.
The problem occurs when I want to match a given XML defintion with one already held in the DB. I currently do this by...
Shredding the XML into a de-normalised table
Using a CTE to pull all the existing data in the database into that same de-normalised form
Matching using a huge WHERE condition (34 lines long)
..This will return me any DataRequestID which exactly matches the XML given. I fear that this method will end up being painfully slow - partly because I don't believe the CTE will do any clever filtering, it will pull all the data every single time before applying the huge WHERE.
I have thought there must be better solutions to this eg
When storing a datarequest, also store a hash of the datarequest somehow and simply match on that. In the case of collision, use the current method. I wanted however to do this using set-logic. And also, I'm concerned about irrelevant small differences in the XML changing the hash - spurious spaces etc.
Somehow perform the matching iteratively from the bottom up. Eg produce a list of filters which match on the lowest level. Use this as part of an IN to match Series. Use this as part of an IN to match DataTasks etc etc. The trouble is, I start to black-out when I think about this for too long.
Basically - Has anyone ever encountered this kind of problem before (they must have). And what would be the recommended route for tackling it? example (pseudo)code would be great :)
To get rid of the possibility of minor variances, I'd run the request through an XML transform (XSLT).
Alternatively, since you've already got the code to parse this out into a denormalized staging table that's fine too. I would then simply using FOR XML to create a new XML doc.
Your goal here is to create a standardized XML document that respects ordering where appropriate and removes inconsistencies where it is not.
Once that is done, store this in a new table. Now you can run a direct comparison of the "standardized" request XML against existing data.
To do the actual comparison, you can use a hash, store the XML as a string and do a direct string comparison, or do a full XML comparison like this: http://beyondrelational.com/modules/2/blogs/28/posts/10317/xquery-lab-36-writing-a-tsql-function-to-compare-two-xml-values-part-2.aspx
My preference, as long as the XML is never over 8000bytes, would be to create a unique string (either VARCHAR(8000) or NVARCHAR(4000) if you have special character support) and create a unique index on the column.