Freigeben über


FetchXml-Beispielcode

Um die Verwendung von FetchXml mit C# auszuprobieren, können Sie die statischen OutputFetchRequest-Methoden in diesem Artikel verwenden, indem Sie die entsprechenden Schnellstartbeispiele anpassen:

Hinweis

Beispielcode zum Abrufen von Daten auf Seiten finden Sie unter Beispiele für Auslagerungs-Cookies.

Sie können die folgende statische OutputFetchRequest-Methode verwenden, um FetchXml-Abfragen in einer Konsolenanwendung zu testen.

Die OutputFetchRequest-Methode zeigt, wie die FetchExpression-Klasse und die IOrganizationService.RetrieveMultiple-Methode verwendet werden, um eine EntityCollection zurückzugeben, die die angeforderten Daten enthält.

Die OutputFetchRequest-Methode hängt vom ConsoleTables-NuGet-Paket ab und erfordert, dass alle Entitäten oder Link-Entitätselemente Attributelemente enthalten sind, was eine bewährte Methode ist.

/// <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;
    }
}

SDK für .NET-Schnellstartbeispiel aktualisieren

Sie können das Beispiel Schnellstart: Eine SDK für .NET-Anforderung ausführen (C#) zum Testen von Abfragen mit den folgenden Schritten anpassen:

  1. ConsoleTables-NuGet-Paket installieren

  2. Fügen Sie die folgenden Anweisungen mithilfe von Anweisungen an den Anfang der Datei program.cs ein.

    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Query;
    using System.Text;
    using System.Xml.Linq;
    
  3. Kopieren Sie die Methode OutputFetchRequest und fügen Sie sie unter der Methode Main ein.

  4. Bearbeiten Sie die Main-Methode, um Ihre Abfrage festzulegen, und verwenden Sie die OutputFetchRequest-Methode.

        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();
        }
    

Wenn Sie das Programm mit der OutputFetchRequest-Methode ausführen, sollte die Ausgabe wie folgt aussehen:

 ---------------------------------------------------------------------------------------------------------
 | 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)      |
 ---------------------------------------------------------------------------------------------------------

Daten mithilfe von FetchXml abfragen
Daten mithilfe von FetchXml abrufen
Beispiel: Verwendung FetchXML mit einem Paging-Cookie
Beispiel: Verwenden Sie Aggregation in FetchXML
Beispiel: Konvertieren von Abfragen zwischen FetchXML und QueryExpression