Thursday 7 July 2011

CRM 2011 - Using FetchXML in Plugins

In the past, CRM provided the standard web service to a plugin and the plugin would use that to perform all data operations. In CRM 2011 the service passed through IPlugin interface is the WCF SOAP Organisation Service (IOrganisationService).
This new service no longer has the "Fetch" method. This has instead been replaced by a FetchExpression that is executed using the IOrganisationService.RetrieveMultiple method. An example of how this is undertaken:

EntityCollection results = service.RetrieveMultiple(new FetchExpression(fetchXml));
As you can see from this, the results returned are not in XML format but instead as an entity collection. This will make it easier for you to return information for a single type of entity as you can then use strongly typed objects generated by the tool provided in the SDK. Where you will lose functionality is in doing complex queries returning information from more than one entity. For example the following Fetch should select all topics for the incident and their corresponding active data source values:

<fetch mapping="logical" distinct="true" version="1.0">   <entity name="incident">     <filter>       <condition attribute="incidentid" operator="eq" value="{0}" />     </filter>     <link-entity name="incident_topic" from="incidentid" to="incidentid">       <link-entity name="incident_topic" from="incident_topicid" to="incident_topicid">         <attribute name="name" />         <attribute name="incident_topicid" />         <link-entity name="data_source_mapping" from="incident_topicid" to="incident_topicid" link-type="outer">           <attribute name="outbound" />           <filter>             <condition attribute="statecode" operator="eq" value="0" />           </filter>         </link-entity>       </link-entity>     </link-entity>   </entity> </fetch>
 
This will not map directly to an entity BUT the good thing is the information is actually returned, just not in a nice easy way to get at but where there is a will there is a way.  All values that are return within the Entity.Attributes property are in fact an AliasedValue. The following code allows you to exploit this to get the information back you require:

       foreach (var topic in results.Entities)
       {
           TestType test = new TestType();
 
           foreach (var attribute in topic.Attributes)
           {
               // set the outbound of the record
               if(((AliasedValue)attribute.Value).EntityLogicalName == Constants.Entities.DataSourceMapping &&
                   ((AliasedValue)attribute.Value).AttributeLogicalName == Constants.Attributes.Outbound)
               {
                   test.outbound = ((AliasedValue) attribute.Value).Value.ToString();
               }
                    
               // set the name of the record
               if (((AliasedValue)attribute.Value).EntityLogicalName == Constants.Entities.IncidentTopic &&
                   ((AliasedValue)attribute.Value).AttributeLogicalName == Constants.Attributes.Name)
               {
                   test.name = ((AliasedValue) attribute.Value).Value.ToString();
               } 
           }
 
           tests.Add(test);
       }

This is a basic example of this, but as you can see it is a solution to allow the use of FetchXML within CRM 2011 plugins to be more complex than standard multi level filtering.

No comments:

Post a Comment