Tag Archives: FetchXml

Query einer Ansicht im Code ausführen

Es kommt häufig vor das eine bestimmte Aktion auf einer Menge Records einer Entität ausgeführt werden soll. Natürlich soll konfiguriert werden können welche Records das sind. Was liegt da näher als die bereits vorhandene “Advance Find” zu verwenden um diesen Filter zu definieren? Continue reading

Count mit FetchXml

Leider ist es weder mit einer QueryExpression noch mit Linq möglich eine Aggregation (Server seitig) in einer Abfrage durchzuführen.
Deshalb ist man gezwungen FetchXml zu benutzten. Hier ein kleines Beispiel wie sich ein Count ausführen lässt.

string fetchXml = String.Format("<fetch distinct='false' no-lock='false' mapping='logical' aggregate='true'>" +
"<entity name='account' > " +
"<attribute name='accountid' aggregate='count' alias='accountCount' /> " +
"</entity>" +
"</fetch>");

var request = new ExecuteFetchRequest { FetchXml = fetchXml };
var response = (ExecuteFetchResponse)organizationService.Execute(request);
var fetchResult = XDocument.Parse(response.FetchXmlResult);
return int.Parse(fetchResult.Descendants("accountCount").Single().Value);

FetchXML und Wildcards

In diesem Post geht es um die Interpretation von Wildcards von Dynamics CRM. Um das Problem zu erklären, muss ich etwas ausholen. Die Anforderung war folgende: Ein CRM Dialog soll die Möglichkeit bieten nach Entitäten zu suchen. Die Suche soll mit “Begins With” funktionieren. Gibt der Benutzer für ein Attribut keinen Wert ein, so soll dieses Attribut nicht berücksichtigt werden. Als Filter ist “and” einzusetzen.

Zum bessern Verständnis hier der gewünschte Dialog:
Wildcard_1

Was hat das nun mit FetchXML und Wildcards zu tun? Beim testen fällt folgendes auf:
Wildcard_3

In Worte gefasst: Sobald ein Attribut, dass in die Suche mit einbezogen wird, keinen Wert enthält, wird der Record nicht mehr zurückgeliefert.

Sehen wir uns also die Query an, die abgesetzt wird:
Wildcard_2

Im oben gezeigten Fall, müsste das somit die folgende sein:

<fetch mapping='logical'>
   <entity name='account'>
      <attribute name = 'name'/>
      <attribute name = 'accountid'/>
      <order attribute='name' descending='false' />
      <filter type='and'>
         <condition attribute = 'name' operator='like' value='Stree%'/>
         <condition attribute = 'name' operator='like' value='%'/>
      </filter>
   </entity>
</fetch>

Nach etwas mehr Testing (mit ausführen der FetchExpression über eine Console Application) kam ich zum Schluss:
Der Wildcard Operator “%” steht für “Any Character” aber nicht für “Empty”.

Diese Erkenntnis war sehr ärgerlich, heisst sie doch, dass sich die Anforderung nicht umsetzen lässt. Oder etwas doch? Mit einem Plug-In auf der “RetrieveMultiple” Message müsste sich die Query manipulieren lassen. Und siehe da, es funktioniert. Hier noch der Code für das Plugin.

public class RetrieveMultiple : IPlugin
{
  public void Execute(IServiceProvider serviceProvider)
  {
    var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));

    if (context.InputParameters.Contains("Query") &amp;&amp; context.InputParameters["Query"] is FetchExpression)
    {
      var fetchExpression = (FetchExpression)context.InputParameters["Query"];
      var xDocument = XDocument.Parse(fetchExpression.Query);
      xDocument.Descendants("condition").Where(c => c.Attribute("operator").Value == "like" &amp;&amp; c.Attribute("value").Value == "%").Remove();
      fetchExpression.Query = xDocument.ToString(SaveOptions.DisableFormatting);
    }
  }
}