Exemple de code FetchXml
Pour essayer d’utiliser FetchXml avec C#, vous pouvez utiliser les méthodes statiques OutputFetchRequest
décrites dans cet article en adaptant les exemples de démarrage rapide respectifs :
- Démarrage rapide : exécuter une requête du SDK pour .NET (C#)
- Démarrage rapide : exemple de l’API web (C#)
Notes
Consultez Exemples de cookies de pagination pour obtenir un exemple de code pour récupérer des données dans les pages.
Vous pouvez utiliser la méthode statique OutputFetchRequest
suivante pour tester les requêtes FetchXml dans une application console.
La méthode OutputFetchRequest
démontre comment utiliser la classe FetchExpression et la méthode IOrganizationService.RetrieveMultiple pour renvoyer une EntityCollection contenant les données demandées.
La méthode OutputFetchRequest
dépend du package NuGet ConsoleTables et nécessite que tous les éléments d’attribut de l’élément entity ou link-entity soient inclus, ce qui constitue une pratique recommandée.
/// <summary>
/// Renders the output of a query in a table for a console application
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="fetchXml">The FetchXml query to use.</param>
static void OutputFetchRequest(IOrganizationService service, string fetchXml)
{
FetchExpression fetchExpression = new(fetchXml);
//Retrieve the data
EntityCollection entityCollection = service.RetrieveMultiple(query: fetchExpression);
// Get column names from the FetchXml
List<string> columns = GetColumns(fetchXml);
// Create the table using https://www.nuget.org/packages/ConsoleTables/2.5.0
var table = new ConsoleTables.ConsoleTable(columns.ToArray());
// Add the rows of the table
entityCollection.Entities.ToList().ForEach(entity =>
{
table.Rows.Add(GetRowValues(columns, entity).ToArray());
});
// Write the table to the console
table.Write();
/// <summary>
/// Get a list of column names from the FetchXml
/// </summary>
/// <param name="fetchXml">The fetchXml query</param>
/// <returns></returns>
static List<string> GetColumns(string fetchXml)
{
XDocument fetchDoc = XDocument.Parse(fetchXml);
XElement fetchElement = fetchDoc.Root;
bool isAggregate = !(fetchElement?.Attributes("aggregate") == null &&
(fetchElement?.Attribute("aggregate")?.Value == "true" ||
fetchElement?.Attribute("aggregate")?.Value == "1"));
// There can only be one entity element
XElement entityElement = fetchElement.Element("entity");
// Get the columns from the entity and any related link-entity elements
return GetColumnsFromElement(element: entityElement, isAggregate: isAggregate);
}
/// <summary>
/// Recursive function to get all column names from an entity or nested link-entity elements
/// </summary>
/// <param name="element">The entity or link-entity element</param>
/// <param name="isAggregate">Whether the query uses aggregation</param>
/// <param name="alias">The alias of the link-entity element</param>
/// <returns></returns>
static List<string> GetColumnsFromElement(XElement element, bool isAggregate, string? alias = null)
{
List<string> columns = new();
// Get the attributes from the element
foreach (XElement attribute in element.Elements("attribute"))
{
StringBuilder sb = new();
// Prepend the alias for non-aggregate link-entities
if (!string.IsNullOrWhiteSpace(alias) && !isAggregate)
{
sb.Append($"{alias}.");
}
// Use the attribute alias if there is one
if (attribute.Attribute("alias") != null)
{
sb.Append(attribute.Attribute("alias")?.Value);
}
else
{
//Use the attribute name
sb.Append(attribute.Attribute("name")?.Value);
}
columns.Add(sb.ToString());
}
// Whether the link-entity intersect attribute is true
bool isIntersect = (element.Attribute("intersect") != null) &&
(element.Attribute("intersect")?.Value == "true" ||
element.Attribute("intersect")?.Value == "1");
// The name of the element
string elementName = element.Attribute("name")?.Value;
// The type of element: 'entity' or 'link-entity'
string elementType = element.Name.LocalName;
// This method requires any non-intersect entity to have attributes
if (columns.Count == 0 && !isIntersect)
{
// An non-intersect element with no attribute elements is technically valid,
// but not supported by this method.
throw new Exception($"No attribute elements in {elementType} element named '{elementName}'.");
}
// Look for any child link-entities
foreach (XElement linkEntity in element.Elements("link-entity"))
{
// Use the alias if any
string? linkEntityName;
if (linkEntity.Attribute("alias") != null)
{
linkEntityName = linkEntity.Attribute("alias")?.Value;
}
else
{
linkEntityName = linkEntity.Attribute("name")?.Value;
}
// Recursive call for nested link-entity elements
columns.AddRange(GetColumnsFromElement(linkEntity, isAggregate, linkEntityName));
}
return columns;
}
/// <summary>
/// Returns the values of a row as strings
/// </summary>
/// <param name="columns">The names of the columns</param>
/// <param name="entity">The entity with the data</param>
/// <returns></returns>
static List<string> GetRowValues(List<string> columns, Entity entity)
{
List<string> values = new();
columns.ForEach(column =>
{
if (entity.Attributes.ContainsKey(column))
{
// Use the formatted value if it available
if (entity.FormattedValues.ContainsKey(column) &&
!string.IsNullOrWhiteSpace(entity.FormattedValues[column]))
{
values.Add($"{entity.FormattedValues[column]}");
}
else
{
// When an alias is used, the Aliased value must be converted
if (entity.Attributes[column] is AliasedValue aliasedValue)
{
// When an EntityReference doesn't have a Name, show the Id
if (aliasedValue.Value is EntityReference lookup &&
string.IsNullOrWhiteSpace(lookup.Name))
{
values.Add($"{lookup.Id:B}");
}
else
{
values.Add($"{aliasedValue.Value}");
}
}
else
{
// Use the simple attribute value
values.Add($"{entity.Attributes[column]}");
}
}
}
// Null values are not in the Attributes collection
else
{
values.Add("NULL");
}
});
return values;
}
}
Mettre à jour l’exemple de démarrage rapide du SDK pour .NET
Vous pouvez adapter l’exemple Démarrage rapide : exécuter une requête du SDK pour .NET (C#) pour tester les requêtes en procédant comme suit :
Installez le package NuGet ConsoleTables
Ajoutez la syntaxe suivante à l’aide des instructions en haut du fichier
program.cs
using Microsoft.Xrm.Sdk; using Microsoft.Xrm.Sdk.Query; using System.Text; using System.Xml.Linq;
Copiez et collez la méthode
OutputFetchRequest
sous la méthodeMain
.Modifiez la méthode
Main
pour définir votre requête et utiliser la méthodeOutputFetchRequest
.static void Main(string[] args) { using (ServiceClient serviceClient = new(connectionString)) { if (serviceClient.IsReady) { //WhoAmIResponse response = // (WhoAmIResponse)serviceClient.Execute(new WhoAmIRequest()); //Console.WriteLine("User ID is {0}.", response.UserId); string fetchQuery = @"<fetch top='5'> <entity name='account'> <attribute name='accountclassificationcode' /> <attribute name='createdby' /> <attribute name='createdon' /> <attribute name='name' /> </entity> </fetch>"; OutputFetchRequest(serviceClient, fetchQuery); } else { Console.WriteLine( "A web service connection was not established."); } } // Pause the console so it does not close. Console.WriteLine("Press the <Enter> key to exit."); Console.ReadLine(); }
Lorsque vous exécutez le programme à l’aide de la méthode OutputFetchRequest
, la sortie doit ressembler à ceci :
---------------------------------------------------------------------------------------------------------
| accountclassificationcode | createdby | createdon | name |
---------------------------------------------------------------------------------------------------------
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | Litware, Inc. (sample) |
---------------------------------------------------------------------------------------------------------
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | Adventure Works (sample) |
---------------------------------------------------------------------------------------------------------
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | Fabrikam, Inc. (sample) |
---------------------------------------------------------------------------------------------------------
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | Blue Yonder Airlines (sample) |
---------------------------------------------------------------------------------------------------------
| Default Value | FirstName LastName | 3/25/2023 10:42 AM | City Power & Light (sample) |
---------------------------------------------------------------------------------------------------------
Articles associés
Interroger des données à l’aide de FetchXml
Récupérer des données à l’aide de FetchXml
Exemple : Utilisation FetchXML avec un cookie de pagination
Exemple : Utiliser l’agrégation dans FetchXML
Exemple : Convertir des requêtes entre FetchXML et QueryExpression